C recursive function to calculate Factorial - c

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.

Related

Simple calculator not working with big numbers in C

I'm trying to build a simple calculator that would perform multiplication and addition.
I have this code
#include <stdio.h>
#include <string.h>
long result = 0;
long *resultPointer = &result;
long plus(long *current, long num) {
return (*current + num);
}
long krat(long *current, long num) {
return (*current * num);
}
int main() {
char operator[4];
long num;
printf("%d\n", 0);
while(scanf("%s %li", &operator[0], &num) != EOF){
if (num > 0) {
if (strcmp(operator, "krat") == 0) {
*resultPointer = krat(&result, num);
}
if (strcmp(operator, "plus") == 0) {
*resultPointer = plus(&result, num);
}
printf("%li\n", result);
}
}
return 0;
}
this is the input for the program
plus 123456789
krat 123456789
plus 0
krat 2
krat 3
krat 4
krat 5
krat 6
and this is the output
0
123456789
15241578750190521
30483157500381042
91449472501143126
365797890004572504
1828989450022862520
-7472807373572376496
The problem is that when the numbers get bigger and bigger they turn to negative. Is this the problem with memory allocation for the variables and how to address this?
You're overflowing the variables.
You have two options here. Either find a solution for arbitrarily large numbers (there are libraries you can use) or accept that you cannot use numbers that are to big.
The largest number a signed 64 bit integer can hold (it's obvious from your output that long is 64 bit on your system) is 9223372036854775807 and the largest for an unsigned 64 bit is 18446744073709551615.
It could be worth mentioning that overflow only have a defined behavior for unsigned types.
Other comments
char[4] is not enough to hold "plus", since you need place for the '\0'. Use char[5] instead.
There is no reason to use pointers in this code. Unless you have a very good reason, I would suggest changing to:
long plus(long current, long num) {
return current + num;
}
Which in turn means that you can completely skip the function. You don't need a function to perform addition of two integers since you have the + operator to do that very thing.
Also, your usage of scanf is unsafe. You may write past the end of the array. Do this instead: scanf("%4s %li" Note the 4. It gives a maxlength for the string. On top of that, you should not check scanf for EOF. Read the documentation about what it actually does return.
Variables in programming languages have different size. In c++, long size is at least 32 bits (according to Fundamental Types (C++) (Microsoft website) and C++ Data Types (tutorialspoint website)). So, when you assign a number bigger which needs more bits to store number, it turns to negative (one's complement and 2's complement system in storing numbers).
read C++ Data Types (tutorialspoint website) about the size of each variable in c++ language and also wikipedia has good articles about one's complement and two's complement.

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.

C - erroneous output after multiplication of large numbers

I'm implementing my own decrease-and-conquer method for an.
Here's the program:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
double dncpow(int a, int n)
{
double p = 1.0;
if(n != 0)
{
p = dncpow(a, n / 2);
p = p * p;
if(n % 2)
{
p = p * (double)a;
}
}
return p;
}
int main()
{
int a;
int n;
int a_upper = 10;
int n_upper = 50;
int times = 5;
time_t t;
srand(time(&t));
for(int i = 0; i < times; ++i)
{
a = rand() % a_upper;
n = rand() % n_upper;
printf("a = %d, n = %d\n", a, n);
printf("pow = %.0f\ndnc = %.0f\n\n", pow(a, n), dncpow(a, n));
}
return 0;
}
My code works for small values of a and n, but a mismatch in the output of pow() and dncpow() is observed for inputs such as:
a = 7, n = 39
pow = 909543680129861204865300750663680
dnc = 909543680129861348980488826519552
I'm pretty sure that the algorithm is correct, but dncpow() is giving me wrong answers.
Can someone please help me rectify this? Thanks in advance!
Simple as that, these numbers are too large for what your computer can represent exactly in a single variable. With a floating point type, there's an exponent stored separately and therefore it's still possible to represent a number near the real number, dropping the lowest bits of the mantissa.
Regarding this comment:
I'm getting similar outputs upon replacing 'double' with 'long long'. The latter is supposed to be stored exactly, isn't it?
If you call a function taking double, it won't magically operate on long long instead. Your value is simply converted to double and you'll just get the same result.
Even with a function handling long long (which has 64 bits on nowadays' typical platforms), you can't deal with such large numbers. 64 bits aren't enough to store them. With an unsigned integer type, they will just "wrap around" to 0 on overflow. With a signed integer type, the behavior of overflow is undefined (but still somewhat likely a wrap around). So you'll get some number that has absolutely nothing to do with your expected result. That's arguably worse than the result with a floating point type, that's just not precise.
For exact calculations on large numbers, the only way is to store them in an array (typically of unsigned integers like uintmax_t) and implement all the arithmetics yourself. That's a nice exercise, and a lot of work, especially when performance is of interest (the "naive" arithmetic algorithms are typically very inefficient).
For some real-life program, you won't reinvent the wheel here, as there are libraries for handling large numbers. The arguably best known is libgmp. Read the manuals there and use it.

Adding Big Ints from Array in C Results in No Output

I am new to C (and programming in general, minus a few weeks with Python). I am interested in learning how information is handled on a machine level, therefore I moved to C. Currently, I am working through some simple coding challenges and am having trouble finding information to resolve my current issue.
The challenge is to take N large integers into an array from input and print the sum of the numbers. The transition from Python to C has actually been more difficult than I expected due to the simplified nature of Python code.
Example input for the code below:
5
1000000001 1000000002 1000000003 1000000004 1000000005
Expected output:
5000000015
Code:
int main() {
long long unsigned int sum = 0;
int nums[200], n, i;
scanf("%i", &n);
for (i = 0; i =! n; i++) {
scanf("%i", &nums[i]);
sum = sum + nums[i];
}
printf("%llu", sum);
return 0;
}
The program seems to accept input for N, but it stops there.
One last question, in simple terms, what is the difference between a signed and unsigned variable?
Change your for loop like this
for (i = 0; i != n; i++) {
scanf("%i", &nums[i]);
sum = sum + nums[i];
}
if you say i =! n that is the same as i = !n. What that does is to assign the negated value of n to i. Since you gave a non-zero value to n the result is zero and the loop terminates.
Welcome to C!
Regarding the signed vs unsigned question. signed types can have negative values and unsigned can't. But they both take up the same space (number of bits) in memory. For instance, assuming twos' complement representation and a 32 bit integer, the range of values is
singed : -2^31 to 2^31 - 1 or –2147483648 to 2147483647
unsigned : 0 to 2^32 - 1 or 0 to 4294967295

does modulus function is only applicable on integer data types?

my algorithm calculates the arithmetic operations given below,for small values it works perfectly but for large numbers such as 218194447 it returns a random value,I have tried to use long long int,double but nothing works because modulus function which I have used can only be used with int types , can anyone explain how to solve it or could provide a links that can be useful
#include<stdio.h>
#include<math.h>
int main()
{
long long i,j;
int t,n;
scanf("%d\n",&t);
while(t--)
{
scanf("%d",&n);
long long k;
i = (n*n);
k = (1000000007);
j = (i % k);
printf("%d\n",j);
}
return 0;
}
You could declare your variables as int64_t or long long ; then they would compute the modulus in their range (e.g. 64 bits for int64_t). And it would work correctly only if all intermediate values fit in their range.
However, you probably want or need bignums. I suggest you to learn and use GMPlib for that.
BTW, don't use pow since it computes in floating point. Try i = n * n; instead of i = pow(n,2);
P.S. this is not for a beginner in C programming, using gmplib requires some fluency with C programming (and programming in general)
The problem in your code is that intermittent values of your computation exceed the range of values that can be stored in an int. n^2 for values of n>2^30 cannot be represented as int.
Follow the link above given by R.T. for a way of doing modulo on big numbers. That won't be enough though, since you also need a class/library that can handle big integer values . With only standard C libraries in place, that will otherwise be a though task do do on your own. (ok, for 2^31, a 64 bit integer would do, but if you're going even larger, you're out of luck again)
After accept answer
To find the modulo of a number n raised to some power p (2 in OP's case), there is no need to first calculate power(n,p). Instead calculate intermediate modulo values as n is raise to intermediate powers.
The following code works with p==2 as needed by OP, but also works quickly if p=1000000000.
The only wider integers needed are integers that are twice as wide as n.
Performing all this with unsigned integers simplifies the needed code.
The resultant code is quite small.
#include <stdint.h>
uint32_t powmod(uint32_t base, uint32_t expo, uint32_t mod) {
// `y = 1u % mod` needed only for the cases expo==0, mod<=1
// otherwise `y = 1u` would do.
uint32_t y = 1u % mod;
while (expo) {
if (expo & 1u) {
y = ((uint64_t) base * y) % mod;
}
expo >>= 1u;
base = ((uint64_t) base * base) % mod;
}
return y;
}
#include<stdio.h>
#include<math.h>
int main(void) {
unsigned long j;
unsigned t, n;
scanf("%u\n", &t);
while (t--) {
scanf("%u", &n);
unsigned long k;
k = 1000000007u;
j = powmod(n, 2, k);
printf("%lu\n", j);
}
return 0;
}

Resources