Stuck on maximum unsigned short variable prompt - c

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;

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);
}

Related

Long Long Decimal Binary Representation using C

I've been trying to print out the Binary representation of a long long integer using C Programming
My code is
#include<stdio.h>
#include <stdlib.h>
#include<limits.h>
int main()
{
long long number, binaryRepresentation = 0, baseOfOne = 1, remainder;
scanf("%lld", &number);
while(number > 0) {
remainder = number % 2;
binaryRepresentation = binaryRepresentation + remainder * baseOfOne;
baseOfOne *= 10;
number = number / 2;
}
printf("%lld\n", binaryRepresentation);
}
The above code works fine when I provide an input of 5 and fails when the number is 9223372036854775807 (0x7FFFFFFFFFFFFFFF).
1.Test Case
5
101
2.Test Case
9223372036854775807
-1024819115206086201
Using a denary number to represent binary digits never ends particularly well: you'll be vulnerable to overflow for a surprisingly small input, and all subsequent arithmetic operations will be meaningless.
Another approach is to print the numbers out as you go, but using a recursive technique so you print the numbers in the reverse order to which they are processed:
#include <stdio.h>
unsigned long long output(unsigned long long n)
{
unsigned long long m = n ? output(n / 2) : 0;
printf("%d", (int)(n % 2));
return m;
}
int main()
{
unsigned long long number = 9223372036854775807;
output(number);
printf("\n");
}
Output:
0111111111111111111111111111111111111111111111111111111111111111
I've also changed the type to unsigned long long which has a better defined bit pattern, and % does strange things for negative numbers anyway.
Really though, all I'm doing here is abusing the stack as a way of storing what is really an array of zeros and ones.
As Bathsheba's answer states, you need more space than is
available if you use a decimal number to represent a bit sequence like that.
Since you intend to print the result, it's best to do that one bit at a time. We can do this by creating a mask with only the highest bit set. The magic to create this for any type is to complement a zero of that type to get an "all ones" number; we then subtract half of that (i.e. 1111.... - 0111....) to get only a single bit. We can then shift it rightwards along the number to determine the state of each bit in turn.
Here's a re-worked version using that logic, with the following other changes:
I use a separate function, returning (like printf) the number of characters printed.
I accept an unsigned value, as we were ignoring negative values anyway.
I process arguments from the command line - I tend to find that more convenient that having to type stuff on stdin.
#include <stdio.h>
#include <stdlib.h>
int print_binary(unsigned long long n)
{
int printed = 0;
/* ~ZERO - ~ZERO/2 is the value 1000... of ZERO's type */
for (unsigned long long mask = ~0ull - ~0ull/2; mask; mask /= 2) {
if (putc(n & mask ? '1' : '0', stdout) < 0)
return EOF;
else
++printed;
}
return printed;
}
int main(int argc, char **argv)
{
for (int i = 1; i < argc; ++i) {
print_binary(strtoull(argv[i], 0, 10));
puts("");
}
}
Exercises for the reader:
Avoid printing leading zeros (hint: either keep a boolean flag that indicates you've seen the first 1, or have a separate loop to shift the mask before printing). Don't forget to check that print_binary(0) still produces output!
Check for errors when using strtoull to convert the input values from decimal strings.
Adapt the function to write to a character array instead of stdout.
Just to spell out some of the comments, the simplest thing to do is use a char array to hold the binary digits. Also, when dealing with bits, the bit-wise operators are a little more clear. Otherwise, I've kept your basic code structure.
int main()
{
char bits[64];
int i = 0;
unsigned long long number; // note the "unsigned" type here which makes more sense
scanf("%lld", &number);
while (number > 0) {
bits[i++] = number & 1; // get the current bit
number >>= 1; // shift number right by 1 bit (divide by 2)
}
if ( i == 0 ) // The original number was 0!
printf("0");
for ( ; i > 0; i-- )
printf("%d", bits[i]); // or... putchar('0' + bits[i])
printf("\n");
}
I am not sure what you really want to achieve, but here is some code that prints the binary representation of a number (change the typedef to the integral type you want):
typedef int shift_t;
#define NBITS (sizeof(shift_t)*8)
void printnum(shift_t num, int nbits)
{
int k= (num&(1LL<<nbits))?1:0;
printf("%d",k);
if (nbits) printnum(num,nbits-1);
}
void test(void)
{
shift_t l;
l= -1;
printnum(l,NBITS-1);
printf("\n");
l= (1<<(NBITS-2));
printnum(l,NBITS-1);
printf("\n");
l= 5;
printnum(l,NBITS-1);
printf("\n");
}
If you don't mind to print the digits separately, you could use the following approach:
#include<stdio.h>
#include <stdlib.h>
#include<limits.h>
void bindigit(long long num);
int main()
{
long long number, binaryRepresentation = 0, baseOfOne = 1, remainder;
scanf("%lld", &number);
bindigit(number);
printf("\n");
}
void bindigit(long long num) {
int remainder;
if (num < 2LL) {
printf("%d",(int)num);
} else {
remainder = num % 2;
bindigit(num/2);
printf("%d",remainder);
}
}
Finally I tried a code myself with idea from your codes which worked,
#include<stdio.h>
#include<stdlib.h>
int main() {
unsigned long long number;
int binaryRepresentation[70], remainder, counter, count = 0;
scanf("%llu", &number);
while(number > 0) {
remainder = number % 2;
binaryRepresentation[count++] = remainder;
number = number / 2;
}
for(counter = count-1; counter >= 0; counter--) {
printf("%d", binaryRepresentation[counter]);
}
}

program to print armstrong numbers between two integers in c.Not able to find error in code

I wrote the following code to print armstrong numbers between two integers. But I am not able to find the mistake as the code looks fine to me. Please help.
void main()
{
int a,b;
printf("Enter the starting limit");
scanf("%d",&a);
printf("Enter the ending limit");
scanf("%d",&b);
int i;
int sum=0;
for(i=a+1;i<b;i++)
{
char word[50];
sprintf(word,"%d",i);
int temp=strlen(word);
int j;
for(j=0;j<temp;j++)
{
int c=i%10;
sum+=pow(c,temp);
i=i/10;
}
if (sum==i)
{
printf("%d",i);
}
}
}
As someone has answered - I will answer as well. Use only the integer arithmetic. No strings or doubles needed
#include <stdio.h>
typedef unsigned long long ull; // for convenience only
ull sum_cubes(ull num)
{
ull result = 0;
while(num)
{
unsigned digit = num % 10;
result += (ull)digit * digit * digit;
num /= 10;
}
return result;
}
#define MIN 0 //or 100 depending if 001 is the 3 digints number or not.
#define MAX 1000
int main(void)
{
for(ull num = MIN; num < MAX; num++)
{
if(num == sum_cubes(num))
{
printf("Hurray!! Found - %llu\n", num);
}
}
}
You use i in the control expression of the outer for loop but in the inner loop you are modifying i with the i=i/10;.
Even a single execution of that line will ensure that the value of i is lesser than its initial value.
Then this modified i is incremented with the i++ in the outer for loop.
If a is less than b, i<b will always be true, resulting in an infinite loop.
But since you have the number in the form of string in word, you could use that.
for(j=0;j<temp;j++)
{
int c=word[j]-48;
The -48 is used to convert the encoded character value (eg: 2 in ASCII is 50) to the actual number. If the encoding you use is not ASCII, you might have to do something different.
You could also make a copy of i before entering the inner loop and use that variable instead of i in the inner loop like
int t=i, j;
for(sum=j=0;j<temp;j++)
{
int c=t%10;
sum+=pow(c,temp);
t=t/10;
}
You are not resetting the value of sum to 0 before each iteration of the inner loop. You could do that in the first part of the loop (ie, before the first semi-colon) as in the above loop.
Also as pointed out by Bo, pow() returns a float and due to reasons expounded here, inaccuracies might creep in.
So make the type of sum to be float instead of int.
Use of void as the return type of main() is not considered good practice. Use int main() instead. See here.
The part where you take the digits using % operator is also a mistake.
int c=i%10;
On all iterations of the inner loop, value of c would be the last digit of i and you won't get any other digit in c.

Why am i not able to print 47th fibonacci number correctly?

I am using 64 bit operating system ,then also i am not able to print 46th fibonacci number correctly which is less than 4 billion.
#include<cs50.h>
#include<stdio.h>
int main(void)
{
unsigned int n=50;
int array[n];
array[0]=0;
array[1]=1;
printf("%i\n",array[0]);
printf("%i\n",array[1]);
for(int i=2;i<n;i++)
{
array[i]=array[i-1]+array[i-2];
printf("%i\n",array[i]);
}
You have to use long long as your data type of the array. because You are going to store out-range numbers of the integer range.(-2,147,483,648 to 2,147,483,647)
And declaration of int i should be before the for loop.
#include<stdio.h>
int main(void)
{
int n=50;
long long array[n];
array[0]=0;
array[1]=1;
printf("%lli\n",array[0]);
printf("%lli\n",array[1]);
int i;
for(i=2;i<n;i++)
{
array[i]=array[i-1]+array[i-2];
printf("%lli\n",array[i]);
}
}
i am not able to print 46th fibonacci number correctly which is less than 4 billion.
You are most probably going out of range of an integer, which is from -4294967296 to 4294967295.
Change int array[n]; to long long array[n];
Also, the printf's should be changed from %i to %lli
Edit : On running the numbers, you get expected value of F(48) as 4807526976 which is out of range of an integer.
Using Rishikesh Raje's counting system (i.e. 1st Fibonacci is 1) where F(48) is 4807526976, then you weren't able to get F(47) 2971215073 because, as #kaylum commented, you used a signed integer array to hold your values which you need to change to unsigned, and well as change your printf statement to print an unsigned. This would allow you to reach the limit of 32 bit arithmetic:
#include <stdio.h>
#define LIMIT (50)
int main(void) {
unsigned int array[LIMIT] = {0, 1};
printf("%u\n", array[0]);
printf("%u\n", array[1]);
for (size_t i = 2; i < LIMIT; i++)
{
array[i] = array[i - 1] + array[i - 2];
printf("%u\n", array[i]);
}
return 0;
}
To get beyond 32 bits, you can switch to long, or long longs as Rishikesh Raje suggests, but work with unsigned variants if you want to reach the maximum result you can with a given number of bits.
Either Use an unsigned integer array or for more higher values use unsigned long long long array but you don't need an array to print fibonacci series you can simply do this:-
void main()
{
unsigned long long i=1, num1=1, num2=0;
printf("1 \n");
for(i; i<100 ; i++)
{
num1=num1+num2;
num2=num1-num2;
printf("%lli \n", num1);
}
getch();
}

Detecting Overflow In nCr Function

I have two functions here that together compute the nCr:
int factorial(int n) {
int c;
int result = 1;
for (c = 1; c <= n; c++)
{
result = result*c;
}
return result;
}
int nCr(int n, int r) {
int result;
result = factorial(n)/(factorial(r)*factorial(n-r));
return result;
}
I am having trouble with an error check I need to implement. As n gets larger, I won't have the ability to computer n! and this error check has to exist in both nCr and factorial. They both must detect this overflow.
Currently, when I enter a number that is too large for computation, I get a floating type error returned from the command line.
I am having trouble accounting for this overflow check. Any help would be much appreciated, thanks.
A better way of calculating binomial coefficients
typedef unsigned long long ull;
ull nCr(int n, int r) {
ull res = 1;
if (r > n - r) r = n - r;
for (int i = 0; i < r; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
In your code, the maximum value is always factorial(n),
so you only need to check that n! isn't bigger than 2.147.483.647 (max int value).
Please note that the stored max value can be different based on the size of the int type in memory (different machines can specify different sizes).
However, the last bit in int type variables is reserved for storing the sign (+ or -), thus the max value can be half of 65.535 and 4.294.967.295 i.e. 32.767 and 2.147.483.647 for int types.
SIZE_OF_INT(bits) MAX VALUE(UNSIGNED) MAX_VALUE(SIGNED)
---------------------------------------------------------------
16 65.535 32.767
32 4.294.967.295 2.147.483.647
The value of 13! can go beyond the max value of the int type (in 32 bit).
12! = 479.001.600 and
13! = 6.227.020.800
So, you need to check in nCr(int n, int r) that the max value of n is always less than 13 (i.e. n<=12) and r<=n.
And in factorial(int n): n<=12.

How to fix SIGSEGV? (Error while dealing with large values upto 1000000 in Fibonacci Series)

Tried to develop a code that quickly finds Fibonacci values.
But the problem is I get SIGSEGV error when input is of order 1000000.
Also from other questions around here I came to know that it may be because of stack memory that exceeds limit during runtime. And I guess that is the case here.
#include<stdio.h>
unsigned long long int a[1000001] = {0};
unsigned long long int fib(int n)
{
unsigned long long int y;
if(n==1 || n==0)
return n;
if (a[n] != 0)
return a[n];
else
{
y=fib(n-1)+fib(n-2);
a[n] = y;
}
return y;
}
main()
{
int N;
unsigned long long int ans;
a[0] = 1;
a[1] = 1;
scanf(" %d",&N);
ans = fib(N+1);
printf("%llu",ans);
}
How do I fix this code for input value of 1000000?
Here's a better approach (which can still be significantly improved) that will calculate Fibonacci numbers for you:
unsigned long long Fibonacci(int n)
{
unsigned long long last[2] = { 0, 1 }; // the start of our sequence
if(n == 0)
return 0;
for(int i = 2; i <= n; i++)
last[i % 2] = last[0] + last[1];
return last[n % 2];
}
However, you are not going to be able to calculate the millionth Fibonacci number with it, because that number is much, much, much, much larger than the largest number that can fit in an unsigned long long.
Instead of using the stack, use your own variables to track state. Essentially, do the function calls and returns with your own code.
The best way really is just to switch the algorithm entirely to one that's efficient. For example, to calculate fib(6), your code calculates fib(4) twice, once when fib(5) asks and once when fib(6) asks.

Resources