Reputation: 986
I am a bit confused about the behavior of c when it comes to adding large numbers. This is probably a beginner's question but would appreciate any help.
unsigned long total = 0;
total = 1124073472 + 2835349503;
total += 2533359615;
printf("Total: %u\n", total);
The total which gets printed above is not correct. The first add result is fine but the third add throws the total off. I am thinking it is because of overflow. My question is what is a possible solution? Is there a solution without using third party libraries?
Note: I have tried various data types for total. Some of them are DWORD64, INT64, LONG64 etc.
Thanks in Advance.
Upvotes: 2
Views: 5915
Reputation: 1177
Well almost(!) everyone is right at there point. I think you can look @ following two page as well. It will really give you some better idea about how you can handle a really BIG numbers :
Upvotes: 1
Reputation: 16406
Your code is buggy. You should replace %u
with %lu
in your printf statement to match the type of total
. That is sufficient if you're on a system with 32 bit ints and 64 bit longs. But if you're using some other sort of system, you may need to use unsigned long long
as noted in some of the other answers.
Upvotes: 0
Reputation: 62323
The following code ought to work under Visual C++:
unsigned __int64 total = 0;
total = 1124073472LL + 2835349503LL;
total += 2533359615LL;
printf("Total: %I64u\n", total);
Upvotes: 0
Reputation: 343
The code has two problems:
The unsigned long has only 32 bit in 32 bit systems. You need to use long long (and turn on the C99 standar in the compiler settings), or INT64 or something like that.
The %u in the printf format string is for 32 (or less) bit wide numbers. You need to use %llu instead.
Upvotes: 0
Reputation: 140540
The mathematical sum of these three numbers is larger than 232, and you're using unsigned long
, which is 32 bits wide on Windows (even if you compile your program with 64 bit pointers -- this is a willful violation of C89 on Microsoft's part), so the C and C++ standards specify that it wraps around. The number you get is 1124073472 + 2835349503 + 2533359615 - 232.
If you use a 64-bit type, you have to change the printf
format specifier to match. This code will give the mathematically expected answer on a C99-compliant system:
#include <stdio.h>
int main(void)
{
unsigned long long total = 1124073472 + 2835349503;
total += 2533359615;
printf("Total: %llu\n", total);
return 0;
}
No version of MSVC is C99-compliant, however. I don't know the appropriate type declaration or printf
format specifier for MSVC.
Addenda: 1) Addition is not specified to wrap around on overflow for signed types; it's undefined behavior. This most commonly bites people who use signed loop indices when the loop limit is data-dependent. 2) If you were doing math with numbers that could potentially be bigger than 264, even long long
would not save you. C and (as far as I know) C++ do not have true "bignum" types; you'll need a third party library.
Upvotes: 3
Reputation: 320
It is indeed an overflow. You will probably want to create your own "BigNumber" class to perform arithmetic on arbitrarily large numbers. However, I'd recommend using a library if possible. Writing your own "BigNumber" class can be a bit of a chore. Check out the ones posted here - Class for calculating arbitrarily large numbers?
If you don't use them, you can at least use them as guidance.
Upvotes: 0
Reputation: 2166
Have you tried "unsigned long long int"? This will certainly be 64 bits, or use uint64_t, if you have stdint.h. Of course, you could run into new overflow problems (it indeed is that) when you choose even larger numbers, and then it's time to use a bignum library like gmp. And do an overflow check before adding, if you do stick with 64 bit numbers. And use "%lld" to print the decimal result in that case.
Upvotes: 0
Reputation: 2155
What you are seeing is indeed because of an overflow but in the print type as others have mentioned since that number fits inside a long
.
You will be able to do operations that fit within the long
data type. If you want to go larger than that you'd need some sort of "Big Integer" function and if you do not want to use a third party library you can implement your own, however you'd be reinventing the wheel and are better off with using a tested library.
Upvotes: 0
Reputation: 224864
You're correct, it's because of overflow. Using a 64-bit type will fix it - you will need to change your printf()
format string to printa 64-bit type too, though. Making total
an unsigned long long
will probably get you a 64-bit type, but the safest way would be to use one of the typedefs from stdint.h
. Here's an example program - I also used inttypes.h
to get PRIu64
.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(int argc, char **argv)
{
uint64_t total = 0;
total = 1124073472 + 2835349503;
total += 2533359615;
printf("Total: %"PRIu64"\n", total);
return 0;
}
Upvotes: 2