Reputation: 433
So, simple procedure, calculate a factorial number. Code is as follows.
int calcFactorial(int num)
{
int total = 1;
if (num == 0)
{
return 0;
}
for (num; num > 0; num--)
{
total *= num;
}
return total;
}
Now, this works fine and dandy (There are certainly quicker and more elegant solutions, but this works for me) for most numbers. However when inputting larger numbers such as 250 it, to put it bluntly, craps out. Now, the first couple factorial "bits" for 250 are { 250, 62250, 15126750, 15438000, 3813186000 } for reference.
My code spits out { 250, 62250, 15126750, 15438000, -481781296 } which is obviously off. My first suspicion was perhaps that I had breached the limit of a 32 bit integer, but given that 2^32 is 4294967296 I don't think so. The only thing I can think of is perhaps that it breaches a signed 32-bit limit, but shouldn't it be able to think about this sort of thing? If being signed is the problem I can solve this by making the integer unsigned but this would only be a temporary solution, as the next iteration yields 938043756000 which is far above the 4294967296 limit.
So, is my problem the signed limit? If so, what can I do to calculate large numbers (Though I've a "LargeInteger" class I made a while ago that may be suited!) without coming across this problem again?
Upvotes: 1
Views: 15906
Reputation: 140833
If i remember well:
unsigned short int = max 65535
unsigned int = max 4294967295
unsigned long = max 4294967295
unsigned long long (Int64 )= max 18446744073709551615
Upvotes: -3
Reputation: 20271
My Windows calculator (Start-Run-Calc) tells me that
hex (3813186000) = E34899D0
hex (-481781296) = FFFFFFFFE34899D0
So yes, the cause is the signed limit. Since factorials can by definition only be positive, and can only be calculated for positive numbers, both the argument and the return value should be unsigned numbers anyway. (I know that everybody uses int i = 0
in for loops, so do I. But that left aside, we should use always unsigned variables if the value can not be negative, it's good practice IMO).
The general problem with factorials is, that they can easily generate very large numbers. You could use a float, thus sacrificing precision but avoiding the integer overflow problem.
Oh wait, according to what I wrote above, you should make that an unsigned float ;-)
Upvotes: 1
Reputation: 11677
In addition to the other comments, I'd like to point out two serious bugs in your code.
Upvotes: 13
Reputation: 57248
If you don't specify signed or unsigned, the default is signed. You can modify this using a command line switch on your compiler.
Just remember, C (or C++) is a very low-level language and does precisely what you tell it to do. If you tell it to store this value in a signed int, that's what it will do. You as the programmer have to figure out when that's a problem. It's not the language's job.
Upvotes: 4
Reputation: 23759
Yes, you hit the limit. An int in C++ is, by definition, signed. And, uh, no, C++ does not think, ever. If you tell it to do a thing, it will do it, even if it is obviously wrong.
Consider using a large number library. There are many of them around for C++.
Upvotes: 9
Reputation: 14449
2^32 doesn't give you the limit for signed integers.
The signed integer limit is actually 2147483647 (if you're developing on Windows using the MS tools, other toolsuites/platforms would have their own limits that are probably similar).
You'll need a C++ large number library like this one.
Upvotes: 21