When I calculate a large factorial, why do I get a negative number?

痴心易碎 提交于 2019-12-04 19:29:59

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.

In addition to the other comments, I'd like to point out two serious bugs in your code.

  • You have no guard against negative numbers.
  • The factorial of zero is one, not zero.

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++.

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.

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 ;-)

You have an overflow problem. Factorials can easily exceed the limits of integers. You could change your function to return doubles, but that will only buy you a little more room. In applications, you often need multiply factorials times very small numbers where the end result will fit inside a double but the intermediate steps will not. Here's an article that explains how to handle this situation: http://www.johndcook.com/blog/2008/04/24/how-to-calculate-binomial-probabilities/

If i remember well:

unsigned short int = max 65535

unsigned int = max 4294967295

unsigned long = max 4294967295

unsigned long long (Int64 )= max 18446744073709551615

Edited source:

Int/Long Max values

Modern Compiler Variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!