Factorial program in C is wrong after 20 [duplicate] - c

This question already has answers here:
Cannot calculate factorials bigger than 20! ! How to do so?
(7 answers)
Closed 6 years ago.
It works up until 20 but if 21 is entered it returns 1419745... when 21 factorial is actually 51090942171709440000. I'm assuming that this is because of the unsigned long maxing out but where does this wrong number (141...) come from and how can I allow the program to work out the factorial of larger numbers?
#include <stdio.h>
unsigned long fact(unsigned long input);
int main()
{
int input;
printf("Enter an integer to find the factorial of: ");
scanf(" %d", &input);
printf("The Factorial of %d = %lu\n" , input, fact(input));
return 0;
}
unsigned long fact(unsigned long input)
{
if (input == 0)
return 1;
else
return input * fact(input - 1);
}

This answers only to half of your question (why it works this way).
The result you get is 21! mod 2^64. This is because you are using a 64-bit system and 21! is greater than the greatest number that can be stored as unsigned integer on 64 bits.
All factorials you compute for values greater than or equal to 21 are wrong; they cannot be represented on 64-bit integers because they are longer than that.
You can try to use unsigned long long as the type of the values returned by function fact() (and change into the printf() format string %lu with %llu); it could help but it depends on some factors. It doesn't help on my architecture, for example.
You can find out if it can help you by checking the value returned by sizeof(unsigned long long). If if is 8 then you are out of luck. 20 is the largest number for what you can compute factorial on that system.
If your purpose is to compute factorials then you have to use a library that knows how to handle large numbers. However, if you need factorials for other computations (for example, for combinations) then you can try to avoid generating large numbers and find a way to match each multiplication with a division. This way the magnitude of the numbers you use is between the limits of 64-bit integers and you can go further than 21.
Or you can use double instead of integers and you are again back in business but with loss of precision. Large floating point numbers store correctly the magnitude of the number and its first digits. The last digits are lost.
I didn't program very much in C/C++ recently, I cannot recommend you a library that can help you do computations with large numbers :-(

The number comes from overflow. Unsigned arithmetic is done modulo (max value of that type), so a little maths should explain why you get the result you do.
The result of signed integer overflow is undefined so you could have got anything if you'd been using signed integers (though the chances are it'd have been exactly the same on a lot of systems)

Related

Decimal To Binary Conversion in C using For

I am not able to convert from decimal to binary in C.Everytime I get a output which is one less than the desired output.For ex.:5 should be 101 but shows up as 100 or 4 should be 100 but shows up as 99.
#include<stdio.h>
#include<math.h>
void main() {
int a,b=0;
int n;
printf("Enter a Decimal Number\n");
scanf("%d",&n);
for(int i=0;n>0;i++) {
a=n%2;
n=n/2;
b=b+(pow(10,i)*a);
}
printf("%d",b);
}
My output is always one less than the correct answer and I dont know why.It fixes the problem if take b as 1 instead of 0 in the beginning but i dont know why.Please Help.I have just started C a few days ago.
pow is a floating-point function; it takes a double argument and returns a double value. In the C implementation you are using, pow is badly implemented. It does not always produce a correct result even when the correct result is exactly representable. Stop using it for integer arithmetic.
Rewrite the code to compute the desired power of ten using integer arithmetic.
Also, do not compute binary numerals by encoding them a decimal within a int type. It is wasteful and quickly runs into bounds of the type. Use either bits within an unsigned type or an array of char. When scanf("%d",&n); executes, it converts the input string into binary and stores that in n. So n is already binary; you do not need to decode it. Use a loop to find its highest set bit. Then use another loop to print each bit from that position down to the least significant bit.
This code seems fine. I quickly tested it on an online compiler and it seems to be working okay.
I am very sure it has to do with different versions of compilers.
compiler which I tested your code in: https://www.onlinegdb.com/online_c_compiler
Edit:
pow() function is not reliable when used with integers since the integer you pass into it as parameter is implicitly converted into data type of double and returns double as output. When you stuff this value into the integer again, it drops the decimal values. Some compilers seem to produce "correct" result with their version of pow() while some don't.
Instead, you can use a different approach to solve your decimal to binary conversion without errors in general use:
#include<stdio.h>
void main() {
int remainder,result = 0,multiplier = 1;
int input;
printf("Enter a Decimal Number\n");
scanf("%d",&input);
while(input){
remainder = input%2;
result = remainder*multiplier + result;
multiplier*=10;
input/=2;
}
printf("The binary version of the decimal value is: %d",result);
}

I need to create a decimal to binary program that can receive input of up to 100,000,000 and output the whole answer without displaying rubbish

As you've read, I created a decimal to binary program and it works well, but it cannot handle user input equal to 100,000,000. My solution is to print each character as it goes, but I do not know what the appropriate loop to use is, and I am also not that great with the math so the main formula to be used is unclear to me. Arrays are not allowed. Any advice is appreciated. Thank you.
#include <stdio.h>
unsigned long long int input,inp,rem=0,ans=0,place_value=1,ans;
int main()
{
printf("\nYou have chosen Decimal to Binary and Octal Conversion!\n");
printf("Enter a decimal number:\n");
scanf("%llu", &input);
inp=input;
while(input){
rem=input%2;
input=input/2;
ans=ans+(rem*place_value);
place_value=place_value*10;
}
printf("%llu in Decimal is %llu in Binary Form.\n", inp,ans);
return 0;
}
Edit: I have already read all your answers and I have done my best to understand them. I was able to understand most of what was brought up but some terms or lessons mentioned will require more time from me to learn. I have already submitted my output without solving the 100,000,000 issue but I intend to use the knowledge I have now to create better outputs. I tried asking a friend of mine and he told me he was able to do it using method 2 found here:https://www.wikihow.com/Convert-from-Decimal-to-Binary. Perhaps my instructor simply wanted to teach us how to fully utilize control structures and data types which is why there are so many restrictions. Thank you all for your time and god bless.
So as the comments have explained, the decimal number 100000000 has the 27-bit binary representation 101111101011110000100000000. We can therefore store that in a 32-bit int with no problem. But if we were to try to store the decimal number 101111101011110000100000000, which just happens to look like a binary number, well, that would require 87 bits, so it won't even fit into a 64-bit long long integer.
And the code in this question does try to compute its result, ans, as a decimal number which just happens to look like a binary number. And for that reason this code can't work for numbers larger than 1048575 (assuming a 64-bit unsigned long long int).
And this is one reason that "decimal to binary" conversion (or, for that matter, conversion to any base) should normally not be done to a result variable that's an integer. Normally, the result of such a conversion — to any base — should either be done to a result variable that's a string, or it should be printed out immediately. (The moral here is that the base only matters when a number is printed out for a human to read, which implies either a string, and/or something printed to, say, stdout.)
However, in C a string is of course an array. So asking someone to do base conversion without using arrays is a perverse, pointless exercise.
If you print the digits out immediately, you don't have to store them in an array. But the standard algorithm — repeated division by 2 (or whatever the base is) generates digits in reverse order, from least-significant to most-significant, which ends up being right-to-left, which is the wrong order to just print them out. Conventional convert-to-digits code usually stores the computed digits into an array, and then reverses the array — but if there's a prohibition against using arrays, this strategy is (again pointlessly) denied to us.
The other way to get the digits out in the other order is to use a recursive algorithm, as #chux has demonstrated in his answer.
But just to be perverse in my own way, I'm going to show another way to do it.
Even though it's generally a horrible idea, constructing the digits into an integer, that's in base 10 but looks like it's in base 2, is at least one way to store things up and get the answer back out with the digits in the right order. The only problem is that, as we've seen, the number can get outrageously big, especially for base 2. (The other problem, not that it matters here, is that this approach won't work for bases greater than 10, since there's obviously no way to construct a decimal number that just happens to look like it's in, say, base 16.)
The question is, how can we represent integers that might be as big as 87 bits? And my answer is, we can use what's called "multiple precision arithmetic". For example, if we use a pair of 64-bit unsigned long long int variables, we can theoretically represent numbers up to 128 bits in size, or 340282366920938463463374607431768211455!
Multiple precision arithmetic is an advanced but fascinating and instructive topic. Normally it uses arrays, too, but if we limit ourselves to just two "halves" of our big numbers, and make certain other simplifications, we can do it pretty simply, and achieve something just powerful enough to solve the problem in the question.
So, to repeat, we're going to represent a 128-bit number as a "high half" and a "low half". Actually, to keeps things simpler, it's not actually going to be a 128-bit number. To keep things simpler, the "high half" is going to be the first 18 digits of a 36-digit decimal number, and the "low half" is going to be the other 18 digits. This will give us the equivalent of of only about 120 bits, but it will still be plenty for our purposes.
So how do we do arithmetic on 36-digit numbers represented as "high" and "low" halves? Actually, it ends up being more or less the same way we learned how to do pencil-and-paper arithmetic on numbers represented as digits, at all.
If I have one of these "big" numbers, in its two halves:
high1 low1
and if I have a second one, also in two halves:
high2 low2
and if I want to compute the sum
high1 low1
+ high2 low2
-----------
high3 low3
the way I do it is to add low1 and low2 to get the low half of the sum, low3. If low3 is less than 1000000000000000000 — that is, if it has 18 digits or less — I'm okay, but if it's bigger than that, I have a carry into the next column. And then to get the high half of the sum, high3, I just add high1 plus high2 plus the carry, if any.
Multiplication is harder, but it turns out for this problem we're never going to have to compute a full 36-digit × 36-digit product. We're only ever going to have to multiply one of our big numbers by a small number, like 2 or 10. The problem will look like this:
high1 low1
× fac
-----------
high3 low3
So, again by the rules of paper-and-pencil arithmetic we learned long ago, low3 is going to be low1 × fac, and high3 is going to be high1 × fac, again with a possible carry.
The next question is how we're going to carry these low and high halves around. As I said, normally we'd use an array, but we can't here. The second choice might be a struct, but you may not have learned about those yet, and if your crazy instructor won't let you use arrays, it seems that using structures might well be out of bounds, also. So we'll just write a few functions that accept high and low halves as separate arguments.
Here's our first function, to add two 36-digit numbers. It's actually pretty simple:
void long_add(unsigned long long int *hi, unsigned long long int *lo,
unsigned long long int addhi, unsigned long long int addlo)
{
*hi += addhi;
*lo += addlo;
}
The way I've written it, it doesn't compute c = a + b; it's more like a += b. That is, it takes addhi and addlo and adds them in to hi and lo, modifying hi and lo in the process. So hi and lo are passed in as pointers, so that the pointed-to values can be modified. The high half is *hi, and we add in the high half of the number to be added in, addhi. And then we do the same thing with the low half. And then — whoops — what about the carry? That's not too hard, but to keep things nice and simple, I'm going to defer it to a separate function. So my final long_add function looks like:
void long_add(unsigned long long int *hi, unsigned long long int *lo,
unsigned long long int addhi, unsigned long long int addlo)
{
*hi += addhi;
*lo += addlo;
check_carry(hi, lo);
}
And then check_carry is simple, too. It looks like this:
void check_carry(unsigned long long int *hi, unsigned long long int *lo)
{
if(*lo >= 1000000000000000000ULL) {
int carry = *lo / 1000000000000000000ULL;
*lo %= 1000000000000000000ULL;
*hi += carry;
}
}
Again, it accepts pointers to lo and hi, so that it can modify them.
The low half is *lo, which is supposed to be at most an 18-bit number, but if it's got 19 — that is, if it's greater than or equal to 1000000000000000000, that means it has overflowed, and we have to do the carry thing. The carry is the extent by which *lo exceeds 18 digits — it's actually just the top 19th (and any greater) digit(s). If you're not super-comfortable with this kind of math, it may not be immediately obvious that taking *lo, and dividing it by that big number (it's literally 1 with eighteen 0's) will give you the top 19th digit, or that using % will give you the low 18 digits, but that's exactly what / and % do, and this is a good way to learn that.
In any case, having computed the carry, we add it in to *hi, and we're done.
So now we're done with addition, and we can tackle multiplication. For our purposes, it's just about as easy:
void long_multiply(unsigned long long int *hi, unsigned long long int *lo,
unsigned int fac)
{
*hi *= fac;
*lo *= fac;
check_carry(hi, lo);
}
It looks eerily similar to the addition case, but it's just what our pencil-and-paper analysis said we were going to have to do. (Again, this is a simplified version.) We can re-use the same check_carry function, and that's why I chose to break it out as a separate function.
With these functions in hand, we can now rewrite the binary-to-decimal program so that it will work with these even bigger numbers:
int main()
{
unsigned int inp, input;
unsigned long long int anslo = 0, anshi = 0;
unsigned long long int place_value_lo = 1, place_value_hi = 0;
printf("Enter a decimal number:\n");
scanf("%u", &input);
inp = input;
while(input){
int rem = input % 2;
input = input / 2;
// ans=ans+(rem*place_value);
unsigned long long int tmplo = place_value_lo;
unsigned long long int tmphi = place_value_hi;
long_multiply(&tmphi, &tmplo, rem);
long_add(&anshi, &anslo, tmphi, tmplo);
// place_value=place_value*10;
long_multiply(&place_value_hi, &place_value_lo, 10);
}
printf("%u in Decimal is ", inp);
if(anshi == 0)
printf("%llu", anslo);
else printf("%llu%018llu", anshi, anslo);
printf(" in Binary Form.\n");
}
This is basically the same program as in the question, with these changes:
The ans and place_value variables have to be greater than 64 bits, so they now exist as _hi and _lo halves.
We're calling our new functions to do addition and multiplication on big numbers.
We need a tmp variable (actually tmp_hi and tmp_lo) to hold the intermediate result in what used to be the simple expression ans = ans + (rem * place_value);.
There's no need for the user's input variable to be big, so I've reduced it to a plain unsigned int.
There's also some mild trickiness involved in printing the two halves of the final answer, anshi and anslo, back out. But if you compile and run this program, I think you'll find it now works for any input numbers you can give it. (It should theoretically work for inputs up to 68719476735 or so, which is bigger than will fit in a 32-bit input inp.)
Also, for those still with me, I have to add a few disclaimers. The only reason I could get away with writing long_add and long_multiply functions that looked so small and simple was that they are simple, and work only for "easy" problems, without undue overflow. I chose 18 digits as the maximum for the "high" and "lo" halves because a 64-bit unsigned long long int can actually hold numbers up to the equivalent of 19 digits, and that means that I can detect overflow — of up to one digit — simply, with that > 1000000000000000000ULL test. If any intermediate result ever overflowed by two digits, I'd have been in real trouble. But for simple additions, there's only ever a single-digit carry. And since I'm only ever doing tiny multiplications, I could cheat and assume (that is, get away with) a single-digit carry there, too.
If you're trying to do multiprecision arithmetic in full generality, for multiplication you have to consider partial products that have up to twice as many digits/bits as their inputs. So you either need to use an output type that's twice as wide as the inputs, or you have to split the inputs into halves ("sub-halves"), and work with them individually, basically doing a little 2×2 problem, with various carries, for each "digit".
Another problem with multiplication is that the "obvious" algorithm, the one based on the pencil-and-paper technique everybody learned in elementary school, can be unacceptably inefficient for really big problems, since it's basically O(N2) in the number of digits.
People who do this stuff for a living have lots of more-sophisticated techniques they've worked out, for things like detecting overflow and for doing multiplication more efficiently.
And then if you want some real fun (or a real nightmare, full of bad flashbacks to elementary school), there's long division...
OP's code suffers from overflow in place_value*10
A way to avoid no array and range limitations is to use recursion.
Perhaps beyond where OP is now.
#include <stdio.h>
void print_lsbit(unsigned long long x) {
if (x > 1) {
print_lsbit(x / 2); // Print more significant digits first
}
putchar(x % 2 + '0'); // Print the LSBit
}
int main(void) {
printf("\nYou have chosen Decimal to Binary and Octal Conversion!\n");
printf("Enter a decimal number:\n");
//scanf("%llu", &input);
unsigned long long input = 100000000;
printf("%llu in Decimal is ", input);
print_lsbit(input);
printf(" in Binary Form.\n");
return 0;
}
Output
You have chosen Decimal to Binary and Octal Conversion!
Enter a decimal number:
100000000 in Decimal is 101111101011110000100000000 in Binary Form.

Reversing a 5 digit number gives negative number

This is my program for reversing a number.But when I take 5 digits as input, sometimes the answer is correct and positive and sometimes it's negative.
#include<dos.h>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
int main()
{
clrscr();
int a,b,c;
b=0;
printf("Enter the no");
scanf("%d",&a);
c=a;
while(a>0)
{
b=(b*10)+(a%10);
a=a/10;
}
printf("\noriginal no %d",c);
printf("\nreversed no is %d",b);
getch();
return 0;
}
If input: 12111
output: 11121
input: 22333
output: -32214
The limit of integer is from -32768 to 32767, then why is the answer negative?
I tried using long but I got my reversed number as 0.
It looks like this is a 16-bit DOS program? So your int is only 16 bits/2 bytes, and your program is overflowing it.
You could try detecting when this condition will happen, and/or use unsigned to avoid negative numbers or a long instead of int to store bigger values (though this program will still output incorrect answers if you overflow).
What's the overall aim? - Can you just doing it by reversing a string instead?
As Bathsheba mentioned, sizeof(int) is apparently 2, and given the headers you're using, the platform is MS-DOS, which means your int only has 16 bits of information available. Because the first bit is the sign bit, that leaves you with 15 bits and 2^15 is 32768, meaning your range is -32767..+32767. What you want is an unsigned int and %u for scanf and printf. That will allow you to use 0..65535.
Need to be able to handle all 5-digit numbers? Switch to long instead (it won't matter if you make it signed or unsigned other than using %ld or %lu for signed or unsigned respectively), and you will have -2147483648..+2147483647 (signed) or 0..4294967295 (unsigned), which will give you more than enough range for a 5-digit number.
If you have problems with using long and the format is correct for scanf and printf, the problem is in your logic and not your reading of numbers at least.
If the limit is 32767, then reversing 22333 would yield 33322, which is larger than the limit!!!
If you want to use long instead of int, then you should also use "%ld" instead of "%d".

Fibonacci Sequence in C generating negatives?

I'm new to programming and need help in C. I am writing a program to generate a Fibonacci sequence for values with up to 1000 digits.
Here is my code:
#include <stdio.h>
int main(void)
{
int seq[1000];
int i,n;
printf("How many Fibonacci numbers do you want?: ");
scanf("%d",&n);
seq[0] = 0;
seq[1] = 1;
for(i = 2; i < n; i++)
seq[i] = seq[i-1] + seq[i-2];
for (i = 1; i < n; i++)
printf("%d: %d\n", i, seq[i]);
return 0;
}
Now the problem is, the numbers are all correct up until the 47th number. Then it just goes crazy and there's negative numbers and its all wrong. Can anyone see the error in my code? Any help is greatly appreciated.
I am writing a program to generate a Fibonacci sequence for values with up to 1000 digits.
Not yet you aren't. You are storing the values in variables of type int. Commonly such variables are 32 bit values and have a maximum possible value of 2^31 - 1. That equals 2,147,483,647 which is some way short of your goal of reaching 1,000 digits.
The 47th Fibonacci number is the first number to exceed 2,147,483,647. According to Wolfram Alpha, the value is 2,971,215,073.
When your program attempts to calculate such a number it suffers from integer overflow, because the true value cannot be stored in an int. You could try to analyse exactly what happens when you overflow, why you see negative values, but it really doesn't get you very far. Simply put, what you are attempting is clearly impossible with int.
In order to reach 1,000 digits you need to use a big integer type. None of the built-in types can handle numbers as large as you intend to handle.
The comment I posted above has the simple answer, but here's a more complete version: C often represents integers with a sequence of 32 bits, and the range of values they can take on are from -2,147,483,648 to 2,147,483,647.
Notice what the 47th Fibonacci number is? 2,971,215,073
After they overflow, they wrap around to the smallest integer possible; see 2's complement notation for more information!
For a solution, I might suggest a BigInteger structure. But Fibonacci numbers get huge really fast, so I'm not sure you'd really want to calculate that many.
you are not using the correct data type; fibonacci numbers tend to grow really fast. So you probably are going beyond the limit for int: 2^31.
Since int and long are both 32 bit integers (in most cases ->gcc and VS) try using long long .

The program works fine upto 9 digit numbers and fails at 10 digit

This worked on many cases, where most of the variables were ints, except when I wanted to find all the 10 digit numbers that add to, say, 45, then it just gave me an output of zero. Then, I changed all the variables to longs to see if that would make a difference, but it didn't. Any idea on what I should do or am currently doing wrong?
Any help is appreciated.
My program is as follows:
long add_digits(long);
int main()
{
long digit, i, j, limit, l, n, sum=0, rem, result, counter=1;
printf("\nInput digits: ");
scanf("%d", &j);
printf("\nInput number: ");
scanf("%d", &i);
limit=pow(10,j);
for(n=1; n<limit; n++)
{
result = add_digits(n);
if(result==i)
counter++;
}
printf("\n%d\n", counter-1);
return 0;
}
long add_digits(long n)
{
static long sum = 0;
if (n == 0) {
return 0;
}
sum = n%10 + add_digits(n/10);
return sum;
}
Without giving your code any more than a cursory examination, it must be due to hitting the limit of int or long, which are probably 32 bits on your platform. (And the maximum size of a 32 bit number is 10 digits long).
Why not use int64_t which is always 64 bit, and standard since C99? pow may well be giving you problems too; but you could build a quick and dirty multiply by 10 a few times to eliminate that possibility.
The size of ints and longs depend on what you are programming it for so you can't be certain how many bits they use (they both could be 32 bit). You can try and use the library inttypes.h which lets you use int64_t. This way you know for sure your variable is 64bit and should be plenty big enough. Good luck!
As others pointed out that pow() call is the key for your problem. It operates on double's, returning double, then you probably put the result in a 32bit integer on your platform. 10^10 just does not fit in 32 bits, and that's one part of your problem. The other part is accuracy: If you just make an int equal to a double, then you will likely encounter something like in this question.
So the simplest thing to do here is for one probably just raising 10 to the requested power "by hand" (a simple for loop), and using 64 bit types as others suggested to be able to represent more digits.
(Note that although you might try to round the result of pow proper, with large numbers it may lose accuracy on the lowest digits and you again would get to the point that you run your loop incorrect times)

Resources