Why the factorial of 153 has failed in following program - c

I have created a myfun.h header file with two functions in it. A factorial function and amstrong function and a myfun.c file
Here is myfun.h program
void factorial(int n,int *fact)
{
int i;
*fact=1;
for(i=1;i<=n;i++)
*fact=*fact*i;
}
amstrong(int n)
{
int sum=0,num,rem,cube;
num=n;
while(num>0)
{
rem=num%10;
cube=rem*rem*rem;
num=num/10;
sum=sum+cube;
}
if(sum==n)
return(1);
else
return(0);
}
Here is the myfun.c program
#include<stdio.h>
#include "myfun.h"
int main()
{
int num,rev,f,code;
printf("Enter number :");
scanf("%d",&num);
code=amstrong(num);
if(code==1)
printf("\nNumber is amstrong\n");
else
printf("Number is not amstrong\n");
factorial(num,&f);
printf("Factorial of %d is %d ",num,f);
getch();
}
In this the amstrong function is working fine.But the factorial function is giving output 0. I haven't tried it without removing pointer variable. But if i want to run it with pointer variable then what changes i need to do?
The output of program is
Enter number: 153
Number is amstrong
Factorial of 153 is 0

153! = 2.01 E+269.
In case unsigned long long is 64 bits, it can hold a maximum value of 2^64 = 18.45 E+19.
You will need to use some form of "big int" library to calculate huge numbers like these.

This is happening because there is a every data type can hold upto a certain number. The reason that you are getting wrong answer is because the fact of 153 would be bigger then what an int variable can hold. It should work fine for smaller values.
Edit
To store larger numbers you can use long long int data type.

The minimum data type ranges you can use are:
short int and int: -32,767 to 32,767
unsigned short int and unsigned int: 0 to 65,535
long int: -2,147,483,647 to 2,147,483,647
unsigned long int: 0 to 4,294,967,295
int alone cannot store the value given by fact (153). Use smaller values for your case, otherwise change the type: use a long long int instead.

sizeof(long double) = 12bytes on a machine running 32-bit linux. The output can be printed by using %LE in printf. Output will be in exponential form.
EDIT
factorial(20) : 2432902008176640000 when using long long int
This is maximum you can get with long long int type of variable.
For greater ranges use long double.

Related

Why double, long double are always showing 0 as output?

I am writing code to find the distance of a point(25,40000) from a fixed point(47,132000). The distance always printed to be 0.0000.
I have tried checking other combinations, giving smaller values of points, and printing them with %d, it works great.
But with %ld,%lf,%Lf something is not fine. Kindly help.
#include<stdio.h>
#include<math.h>
int main()
{
int x=25,y=40000;
//printf("Enter x,y");
//scanf(%d %d,&x,&y)
long double dist;
dist=sqrt((47-x)*(47-x)+(132000-y)*(132000-y));
printf(" x= %d y=%d dist=%Lf\n",x,y,dist);
return 0;
}
Integer overflow takes place in your code. The below code works -
int main()
{
long long int x=25,y=40000; //int was overflowing and causing you error
long double dist;
dist=sqrt((47-x)*(47-x)+(132000-y)*(132000-y)); //this will safely compute within range and return the desired result
printf("After distance\n");
printf(" x= %lld y=%lld dist=%Lf\n",x,y,dist);
return 0;
}
You were getting wrong output(-nan when I tried out ) because the expression value inside sqrt() was overflowing and becoming negative. (132000-y)*(132000-y) won't fit in an integer range and give negative value. Since, negative square root is not defined, sqrt() returned nan as the result. Changing the type of y to long long int will solve the error.
Hope this helps !

why the value of sum is coming out to be negative? [duplicate]

This question already has answers here:
Sum of positive values in an array gives negative result in a c program
(4 answers)
Closed 4 years ago.
I have written the following c code to find the sum of first 49 numbers of a given array, but the sum is coming out to be negative.
#include<stdio.h>
int main()
{
int i;
long int sum=0;
long int a[50]={846930887,1681692778,1714636916, 1957747794, 424238336, 719885387, 1649760493, 596516650, 1189641422, 1025202363, 1350490028, 783368691, 1102520060, 2044897764, 1967513927, 1365180541, 1540383427, 304089173, 1303455737, 35005212, 521595369, 294702568, 1726956430, 336465783, 861021531, 278722863, 233665124, 2145174068, 468703136, 1101513930, 1801979803, 1315634023, 635723059, 1369133070, 1125898168, 1059961394, 2089018457, 628175012, 1656478043, 1131176230, 1653377374, 859484422, 1914544920, 608413785, 756898538, 1734575199, 1973594325, 149798316, 2038664371, 1129566414};
for(i=0;i<49;i++)
{
sum=sum+a[i];
printf("sum is : %ld\n",sum);
}
printf("\nthe total sum is %ld",sum);
}
i don't know why it is coming so?please help.
Using long long instead of long, the program works:
Ouput: 56074206897
Reason
Range of long: -2^31+1 to +2^31-1
Range of long long: -2^63+1 to +2^63-1
As you can see 2^31-1 = 2147483647 <
56074206897; but 2^63-1 = 9,223,372,036,854,775,807 > 56074206897
This leads to overflow. According to the C standard, the result of signed integer overflow is undefined behavior. What that means is that if this condition ever happens at runtime, the compiler is allowed to make your code do anything. Your program could crash, or produce the wrong answer, or have unpredictable effects on other parts of your code, or it might silently do what you intended.
In your case it is overflowing the maximum value of long int on your system. Because long int is signed, when the most significant bit gets set, it becomes a negative number.
I didn't actually add them up, but just looking at them, I'd say its a pretty safe guess that you are running into an integer overflow error.
A long int has a maximum size of about 2 billion (2^31). If you add more than that, it'll look back around and go to -2^31.
You'll need to use a data type that can hold more than that if you want to sum up those numbers. Probably a long long int should work. If you're sure it'll always be positive, even better to use an unsigned long long int.
As long int has maximum range upto 2,147,483,647, and the value of sum is more than the range.So, it is coming as negative value. You can use the following code...
#include<stdio.h>
int main()
{
int i;
long long int sum=0; //Taking long long int instead of long int
int a[50]={846930887,1681692778,1714636916, 1957747794, 424238336,
719885387, 1649760493, 596516650, 1189641422, 1025202363, 1350490028,
783368691, 1102520060, 2044897764, 1967513927, 1365180541, 1540383427,
304089173, 1303455737, 35005212, 521595369, 294702568, 1726956430,
336465783, 861021531, 278722863, 233665124, 2145174068, 468703136,
1101513930, 1801979803, 1315634023, 635723059, 1369133070, 1125898168,
1059961394, 2089018457, 628175012, 1656478043, 1131176230, 1653377374,
859484422, 1914544920, 608413785, 756898538, 1734575199, 1973594325,
149798316, 2038664371, 1129566414};
for(i=0;i<49;i++)
{
sum=sum+a[i];
printf("sum is : %lld\n",sum);
}
printf("\nTotal sum is %lld",sum);
}
As Vlad from Moscow said this is a overflow issue, which made an undefined behavior. In you system (long int sum) sum does not have capacity to hold the total value. Not sure but you can use long long int sum =0;(after C99). If it still cannot work properly, search for "BigInteger" implement.

Garbage value long long data type

I need to calculate a large number which has length about 9-10 digits. Msdn says that long long type has a range for:
–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
But when i run this code i get a garbage value printed:
#include <stdio.h>
int main(){
int seed = 88888; //This will be always a 5 digit number so the square of
// it will be 9 or 10 digits length
long long square = seed * seed;
printf("square = %lld", square);
getchar();
return 0;
}
Output:
square = -688858048
seed is of type int. seed*seed will also be of type int. And 88888*88888 overflows the size of int. You then assign this garbage value to your long long.
Change the type of seed, or cast in you calculation:
long long square = ((long long) seed) * seed;

C recursive function to calculate Factorial

Im just beginning to learn C programming and figured i would start out at a pretty basic problem of calculating the factorial of a number. My code outputs the correct value up until the factorial of 13 and then gives me the wrong answer for when the input is >13. My code is:
#include<stdio.h>
long int factorial(int);
int main()
{
int num;
long int fact;
printf("Please type the number you want factoralized: ");
scanf("%d",&num);
fact = factorial(num);
printf("%d",fact);
return 0;
}
long int factorial(int dig)
{
long int facto;
if (dig>1)
facto = dig * factorial(dig-1);
else if (dig=1)
facto = 1;
return facto;
}
When i input 13 it returns 1932053504 instead of the expected 6227020800
You are probably overflowing the LONG_MAX value on your platform which leads to undefined behaviour. You can use unsigned long (or unsigned long long) but they wouldn't hold for much longer either.
Your options are limited here. You could use libraries, such as GNU GMP that support arbitrarily large integers. Otherwise, you'll have to implement it yourself similar to GMP.
On another note,
else if (dig=1)
is not what you want. It should be
else if ( dig == 1 )
Or you can simply use else {...} here unless you intend to check against negative numbers.

Explaination of an output

Hi I have implemented a C code in visual C++ and and did some modification in it for debugging. Here is the code
long long unsigned factorial(long long unsigned int * n) {
if (*n<=1) return 1;
else {
(*n)--;//This statement here .......
printf("calculating %d * factorial %d \n",*n,*n); -- used for debugging
return ((*n+1) * factorial(n));
}
}
The final output(value of factorial) is coming as expected but it is output of debug statement that surprises me.
calculating 4 * factorial 0
calculating 3 * factorial 0
calculating 2 * factorial 0
calculating 1 * factorial 0
120
Same value *n is used twice in every debug statement and it is showing different values. How is this possible that same value when used twice in a statement, gives different results.
I'm only guessing here, but the format code "%d" is for int, while you pass a long long. That's a difference of 32 bits per value. Use "%llu" instead ("ll" for long long, the "u" for unsigned).
Because you are using a wrong format for unsigned long long, test this one:
#include <stdio.h>
long long unsigned factorial(long long unsigned int * n) {
if (*n<=1) return 1;
else {
(*n)--;//This statement here .......
printf("calculating %llu * factorial %llu \n",*n,*n);
return ((*n+1) * factorial(n));
}
}
int main(void)
{
long long unsigned int n = 4ULL;
n = factorial(&n);
printf("%llu\n", n);
return 0;
}
You are modifying the value of n at each recursion iteration.
When you are using recursion with a pointer:
return ((*n+1) * factorial(n));
You first calculating the value of factorial(n). When the last recursion iteration is reached, you already decremented the n till 0.
So, please do not pass n by reference .

Resources