Search code examples
cloopsunsignedshort

Stuck on maximum unsigned short variable prompt


Hey everyone of Stack Overflow!

So I am stuck on this prompt:

"Use a loop to determine the value of n that will produce the largest n! value that could be stored in an unsigned short variable. Print out the maximum value for an unsigned short variable, the value of n that will produce the largest n! that is less than or equal to the maximum value for an unsigned short variable. NOTE: The constant USHRT_MAX contained in limits.h provides the maximum value for an unsigned short variable."

I'm guessing, for the above prompt, that it addresses why when I enter an integer such as 34 into the program, I get 0 as the output for the factorial of 34.

I have already made the code for determining the n! value when n is entered so far, but this new part has me confused.

I don't think this will help, but here is the code I have before this prompt:

#include <stdio.h>
unsigned long Factorial(unsigned int n);
int main(void)
{
    int num[11],i=0,factorials[11];
    printf("Please enter up to 10 integers (q to quit): ");
//Ask for integers until a 'q' is entered and store integer values entered into array 'num'
    while (scanf("%u",&num[i]))
    {
        //Store the factorial of integers entered into array 'factorials'
        factorials[i]=Factorial(num[i]);
        //Print numbers out in a two column table
        printf("%5u %9u\n",num[i],factorials[i]);
        i++;
    }
    return 0;
}

//Calculates the factorial of 'n'
unsigned long Factorial(unsigned int n)
{
    int nFactorial,i=1;
    nFactorial=n;
    while (i<n)
    {
        nFactorial=nFactorial*i;
        i++;
    }
    n=nFactorial;
}

Anyways, if anyone can help out, I'd greatly appreciate it! I know this sounds like a tall order of a question, so even a pointer would help heaps!

Thanks anyone!

Cheers, Will.

EDIT: I apologize in advance if my code is difficult to read, I'm working on making it better

EDIT: I came up with this to answer the prompt so far, but it doesn't seem right. The output value is 8...

//Detemine largest max value of n
for (i=0;Factorial(i)<=USHRT_MAX;i++);
printf("The max value for an unsigned short is %u\n Max value of n: %u\n",USHRT_MAX,i-1);
return 0;

Solution

  • Since you're using a short, you can store the factorial sum in a larger type like unsigned long int.

    int main(void)
    {
        unsigned long int sum = 1;
    
        unsigned int n;
        for( n = 1; sum < USHRT_MAX; n++ ) {
            sum *=n;
        }
    
        printf("%lu\n", sum);
        printf("%u\n", n);
    }
    

    This is kind of cheating as there's no guarantee a long int will be larger than a short, but it's really likely. You can mitigate that by verifying.

    assert( sizeof(unsigned short) < sizeof(unsigned long int) );
    

    The non-cheating way is to check if you're about to overflow. You're gonna want to do this, but you can't.

    USHRT_MAX >= sum * n
    

    sum * n will overflow. Instead, divide both sides by n and check that.

    USHRT_MAX / n >= sum
    

    That will stop just before sum *= n would overflow. We can verify by plugging in some numbers. USHRT_MAX = 23, n = 4 and sum = 6...

    23 / 4 >= 6
    5 >= 6
    

    Note that this is integer division, so it's truncated. That's fine for our purposes.

    #include <stdio.h>
    #include <limits.h>
    
    int main(void)
    {
        unsigned short sum = 1;
        unsigned int n;
    
        for( n = 1; (USHRT_MAX / n) >= sum; n++ ) {
            sum *=n;
        }
    
        // We went one too far
        n--;
    
        printf("%u\n", sum);
        printf("%u\n", n);
    }