C MVS-Input with more than 10 digits - c

Recently I tried to write a code that searches for a certain number in a given n.
The code worked perfectly but when I tried to insert n with more than 10 digits it got realy bad.
Apparently it had nothing to do with the code, I just couldn't insert more than 10 digits.
I must be missing something...
For example this simple code
#include <stdio.h>
int main()
{
long int n;
scanf("%ld", &n);
printf("%ld", n);
return 0;
}
If I feed it 1111111111 it would print the same thing becuase its less than 11 digits
If I try to feed it 11111111111 it would give me something like -1773790777
Why is this happening to me? what am I doing wrong...

I'm guessing you are on a 32-bit machine, which means that the long int is only 32 bits, which means it can hold values between minus 2 billion to plus 2 billion. When you try to enter much more than that, the value wraps over.
You should start using a 64-bit value like long long int if your compiler supports it.

Overflow of signed integers is undefined behaviour. I think your long int is of 4 bytes which is causing overflow when you enter a bigger number than it can hold.

Related

Factorial program in C is wrong after 20 [duplicate]

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)

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 .

What's wrong with my C code? (Prime factors of a big number)

Could you please help me?
I'm a beginner at C and my code doesn't work.
I'm trying to determine largest prime factor of 600851475143 and when I run the code, it just does nothing. Trying with smaller number however works.
long i;
for (i = 600851475143; i > 1; i--)
{
if (600851475143 % i == 0)
{
printf("%d\n", i);
}
};
It's probably a 32-bit system. The number 600851475143 is bigger than 32 bits.
Instead of long i try:
long long i;
And instead of printf("%d\n", i); try:
printf("%lld\n", i);
And use 600851475143LL in place of 600851475143.
First of all, the correct way to print a long is not %d but %ld (d = decimal, ld = long decimal). If long and int have different sizes on your system (which is not unusual), the results would not print correctly to begin with.
Next possible problem is that 600851475143 is more than fits into a 32 bit variable, yet long is only guaranteed to be at least 32 bit. It may be bigger than that, but only 32 bits are guaranteed. So are you sure that long is big enough on your system?
Try
printf("%zu\n", sizeof(long));
if it says 8, everything is fine, if it says only 4, long is not sufficient and you need to use long long instead (and %lld for printf, lld = long long decimal).
Last but not least, you are aware that your loop needs to do 600 billion iterations, aren't you? Even if you have a very fast system with a very fast CPU this will take quite some time to complete. So you will see 600851475143 printed to the screen immediately, but it will take quite some time before your code terminates (or finds another divisor, in case this is not a prime number).
Optionally:
Instead of writing 600851475143, you may write 600851475143LL to let the compiler know you want this number to be of type long long. It seems like the C 2011 standard doesn't require this any longer (numbers are automatically treated as long or long long if required), yet I know that pior to C 2011 some compilers least issued a warning for numbers being bigger than int (or bigger than long).
You can start your loop with the greatest integer less than or equal to the square root of your large number. Then you can find factor pairs working down through the loop. Write a separate function to check whether a given number is prime. If the larger factor of the pair is prime, return it. If the larger is not prime, check if the smaller is prime and if so return it.

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