Adding Big Ints from Array in C Results in No Output - c

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

Related

Why does this factorial function break after a certain point?

So I have this factorial function written in C:
unsigned int factorial(unsigned int n){
int fn = 1;
if(n == 0 || n == 1){
return 1;
} else{
for(int i = 1; i <= n; i++){
fn *= i;
}
}
return fn;
}
I tested it out with smaller numbers like 5 and it worked. Then I put it into this loop:
for(int i = 0; i < 100; i++){
printf("\n%d! = %d", i, factorial(i));
}
When i reaches 17, the factorial is apparently -288522240 which is obviously wrong. These kinds of answers continue until i reaches 34 and it says that the factorial is 0. It then does this for the rest of the numbers.
I don't understand what's wrong with my code. I see no reason for the number to become negative or 0. What's happened here?
100! or 9.3326...E+157 or
9332621544394415268169923885626670049071596826438162146859296389521759999322991560894146397615651828625369792082722375825118521091686400000000000000000000000, a 525 bit number, is outside the range of int - likely 32-bit [-2147483648 ... 2147483647]
Signed integer math that overflows is undefined behavior (UB). In OP's case, it appears that the lower 32-bits of the product fn * i, as 2's complement, was the result. Eventually enough multiplication of even numbers kept shifting the non-zero portion of the product "to the left" and resulted in that lower 32 bits becoming 0.
To calculate large factorials one needs another approach. Example

How to take modulus of a large value stored in array?

Suppose I have a integer array containing digits and I want to take modulus of value stored in it, i.e
int a[36]={1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}
and convert it into a number like 987654321987654321987654321987654321.
In C language long long int permits only 10^18. I want to take modulus with 10^9+7. How can i do that?
Program:
int main()
{
int a[36]={1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9};
long long int temp=0;
int i;
for(i=0;i<36;i++)
{
temp=temp+a[i]*pow(10,i);
}
temp=temp%1000000007;
printf("%lld",temp);
return 0;
}
Since 36 decimal digits is too much for a typical long long, you need to perform your modulus operation during the conversion:
int a[36]={1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9};
long long int temp=0;
for(int i=35 ; i >= 0 ; i--) {
temp = 10*temp + a[i];
temp %= 1000000007;
}
printf("%lld",temp);
I made two changes to your code:
Fixed the way you convert an array of digits to a number - your code used pow, and treated digits at higher indexes as higher-order digits. This creates precision problems once you get past the highest power of ten that can be represented as double.
Moved the %= into the loop - your code does not let the number overflow by keeping the value in the range from 0 to 1000000006, inclusive.
Running this code produces the same value that you would obtain with a library that supports arbitrary precision of integers (I used Java BigInteger here).

Is there a maximum length of integers I can enter for C?

for the b/m, I am trying to sum up the digits of an integer. eg. if I enter 1234, i get the answer 1 + 2 + 3 + 4 = 10.
this works for integers up to 10 digits long. after that, if i enter an integer with 11 digits like 12345678912, it returns me a negative answer.
Could anyone help to explain why this is so please? And if there's anyway I can get around it?
Thank you!
#include <stdio.h>
int main(void)
{
int number, single_digit, sum;
printf("What number would you like to sum:\n");
scanf("%i", &number);
sum = 0;
while(number != 0)
{
single_digit = number % 10;
sum += single_digit;
number = number / 10;
}
printf("The sum of the number is %i.\n", sum);
return 0;
}
Yes, the maximum value an integer can hold is INT_MAX (whose value depends on your platform).
An unsigned int can hold larger (positive) numbers, up to UINT_MAX.
You may be able to fit more in unsigned long or unsigned long long - again, the details are platform-specific. After that, you're looking for a bignum library.
NB. since you just want to sum the digits, using something like haccks' approach is much simpler, and less likely to overflow. It's still possible, though.
The maximum limit for an int is INT_MAX. You are getting -ve value because 12345678912 doesn't fit in the range of int and causes integer overflow.
Better to change your main's body to
sum = 0;
int ch;
printf("Enter the number would you like to sum:\n");
while((ch = getchar()) != '\n' && ch != EOF)
{
sum += ch - '0';
}
printf("The sum of the number is %i.\n", sum);
Since getchar reads single character at a time, you will get your desired output by adding these to sum.
This is happening because an int is only 4 bytes. What that means is any number larger than 2^31 will cause the buffer to overflow. A more detailed explanation can be found here: http://en.wikipedia.org/wiki/Integer_overflow. If you want to get around it, use an unsigned int instead, it will let you go up to 2^32 instead, but it will not let you have any negative numbers.
The int type is (usually) a signed 32-bit integer (you can see your size by printing sizeof(int)*8 to get the number of bits.
This means that the maximum value you can store in an int is 2^32 - 1, but, because int is signed, the range is actually half that.
In C a specific type of integer is stored in a fixed amount of memory. On all current architectures an int is stored in 32 bits. Since int carries a sign, the most significant bit is assigned to the sign. This means that the biggest integer you can store in an int is 2^31 - 1. You are seeing a negative number because the your int is overflowing into the sign bit and making it negative.
Number types in c are limited. You can find the max ints in limits.h
You should read the input as a string (char array) and process each character to allow arbitrary* lenght numbers.
*The sum still need to be less than max int. the input string must be big enough to contain what the user writes
An integer with 11 digits like 12345678912 if too large to fit in number which is an int on your platform.
In C, an int has of range of at least -32767 to 32767. On your platform it apparently has the range -2147483648 to +2147483647.
If code is to read the entire integer at once, the maximum number of digits is limited by the range of the various available integer types.
C provides an integer type called intmax_t and its unsigned partner uintmax_t which typically has the maximum range available on a given platform.
#include <inttypes.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void MaximalSumOFDigits(void) {
uintmax_t number;
double widthf = log10(UINTMAX_MAX);
int widthi = ((int) floor(widthf)) - 1;
char buf[widthi + 2];
printf("What number would you like to sum: (up to %d digits)\n", widthi);
fgets(buf, sizeof buf, stdin);
char *endptr;
errno = 0;
number = strtoumax(buf, &endptr, 10);
if (*endptr != '\n')
Handle_UnexpectedInput();
if (errno) // This should not easily happen as buffer has limited length
Handle_TooBigANumber();
int sum = 0;
while (number > 0) { // avoiding ASCII dependence
sum += number % 10;
number /= 10;
}
printf("The sum of the number is %d.\n", sum);
}
With a 64-bit uintmax_t, allows numbers up to
18446744073709551615 (any 19 digit number and some 20 digit numbers)
The above suggests to the user input limit of limit of
_9999999999999999999 (any 19 digit number)

Allocating large memory in C (Project Euler Prob)

I was trying to solve a problem using C on project euler click here
Here is the code. It works fine for 10 values but for 1000 values it gives a wrong output. I noticed that it gives a right output till 32. I think I'm exceeding the memory or something. How do I allocate memory for such a large array?
#include <stdio.h>
int main() {
int a[10], i, sum=1, b=0;
for(i = 1; i < 10; i++) {
a[0] = 1;
a[i] = sum + a[i-1];
sum = sum + a[i-1];
}
for(int j = 1;j > 0; j++) {
b = b + sum%10;
if(sum<10)
break;
sum = sum/10;
}
printf("%d\n",b);
return 0;
}
You might try computing 21000 as an 80-bit long double, then using sprintf to convert it to a string, then summing the digits of that string.
Why this works:
Floating-point types store numbers as a mantissa times an exponent. The exponent is always a power of two, and the mantissa can be 1. For a long double, the exponent can be up to 216383. printf and friends, on modern implementations, will correctly print out the digits of a floating-point number.
Code:
int main() {
char buf[1024]; int ans = 0;
sprintf(buf, "%.0f", 0x1.0p1000);
for (int i = 0; buf[i]; i++) ans += buf[i] - '0';
printf("%i\n", ans);
}
I noticed that it gives a right output till 32
That is, because the integer type you're using has 32 bits. It simply can't hold larger numbers. You can't solve it the conventional way.
Here's what I'd suggest: First let's estimate how many digits that number will have. Every time a number gets 10-fold in decimal writing a new digit is required. So the number of digits for a number in decimal is given by ceil(log10(n)). So for 2^1000 you need ceil(log10(2^1000)) digits, but that is just ceil(1000*log10(2)) = 302, so you'll need 302 decimal digits to write it down.
This gives the next idea: Write down the number 1 in 302 digits, i.e. 301 times '0' and one '1' in a string. Then double the string 1000 times, by adding it to itself just like in elementary school, carrying the overflowing digits.
EDIT I think I should point out, that the problem encountered is the whole point of this Project Euler problem. Project Euler problems all have in common, that you can not solve them by using naive programming methods. You must get creative to solve them!

C code running well only upto a certain point

I wrote this simple code to generate 4th power of all positive integers up to 1005. It works fine only up to integer 215. After that it gives erroneous readings. why so?
# include<stdio.h>
int main(void)
{
int i;
unsigned long long int j;
for (i = 1; i <= 1005; i++){
j = i*i*i*i;
printf("%i.........%llu\n",i,j);
}
return 0;
}
You can fix it by making this small change.
unsigned long long i;
The problem is that in the line j = i*i*i*i;, the right hand side is being calculated as an int before it is being assigned to j. Because of this if i^4 exceeds integer limits, it will basically start to go first negative and start cycling around when higher bits get clipped. When the negative number is assigned to j, since j is unsigned, -i becomes max - i, which is where the huge numbers come from. You will also need to change the printf format specifier from %i to %llu for i.
You can also fix this by doing the below
j = (unsigned long long)i*i*i*i;
This basically forces a cast up to the type of j before performing the multiplication.
Sanity check - 215 ^4 = 2136750625 which is very close to the upper limit of signed int of 2,147,483,647.
i*i produces an int. And so do i*i*i and i*i*i*i. 215 is the greatest positive integer whose 4th power fits into a 32-bit int.
Beyond that the result is typically truncated (typically because strictly speaking you are having a case of undefined behavior; signed integer overflows result in UB per the C standard).
You may want to cast i to unsigned long long or define it as unsigned long long, so the multiplications are 64-bit:
j = (unsigned long long)i*i*i*i;

Resources