1

所以,简单的程序,计算一个阶乘数。代码如下。

int calcFactorial(int num)
{
    int total = 1;

    if (num == 0)
    {
        return 0;
    }

    for (num; num > 0; num--)
    {
        total *= num;
    }

    return total;
}

现在,对于大多数数字来说,这工作得很好而且很漂亮(当然有更快、更优雅的解决方案,但这对我有用)。但是,当输入更大的数字(例如 250)时,坦率地说,就是废话。现在,250 的前几个阶乘“位”是 { 250, 62250, 15126750, 15438000, 3813186000 } 以供参考。

我的代码吐出 { 250, 62250, 15126750, 15438000, -481781296 } 这显然是关闭的。我的第一个怀疑可能是我违反了 32 位整数的限制,但鉴于 2^32 是 4294967296,我不这么认为。我唯一能想到的可能是它违反了有符号的32 位限制,但它不应该能够考虑这种事情吗?如果被签名是问题,我可以通过使整数无符号来解决这个问题,但这只是一个临时解决方案,因为下一次迭代产生 938043756000 远高于 4294967296 限制。

那么,我的问题是签名限制吗?如果是这样,我能做些什么来计算大数(虽然我有一个“LargeInteger”类我前一段时间可能适合!)而不会再次遇到这个问题?

4

6 回答 6

21

2^32 没有给你有符号整数的限制。

有符号整数限制实际上是2147483647(如果您使用 MS 工具在 Windows 上进行开发,其他工具套件/平台将有自己的限制,可能类似)。

您将需要一个像这样的 C++ 大量库。

于 2008-10-25T12:41:50.890 回答
13

除了其他评论之外,我想指出您的代码中的两个严重错误。

  • 你对负数毫无防备。
  • 零的阶乘是一,而不是零。
于 2008-10-25T12:46:25.903 回答
9

是的,你达到了极限。根据定义,C++ 中的 int 是有符号的。而且,呃,不,C++ 永远不会思考。如果你告诉它做一件事,它就会做,即使它显然是错误的。

考虑使用大量库。对于 C++,它们中有很多。

于 2008-10-25T12:43:19.670 回答
4

如果您不指定有符号或无符号,则默认为有符号。您可以使用编译器上的命令行开关来修改它。

请记住,C(或 C++)是一种非常低级的语言,并且完全按照您的指示去做。如果你告诉它把这个值存储在一个有符号的 int 中,它就会这样做。作为程序员,你必须弄清楚什么时候会出现问题。这不是语言的工作。

于 2008-10-25T12:44:36.907 回答
1

我的 Windows 计算器 ( Start-Run-Calc ) 告诉我

hex (3813186000) =         E34899D0
hex (-481781296) = FFFFFFFFE34899D0

所以是的,原因是签名限制。由于阶乘在定义上只能是正数,并且只能为正数计算,因此参数和返回值都应该是无符号数。(我知道每个人都使用int i = 0for 循环,我也是。但抛开这一点,如果值不能为负,我们应该始终使用无符号变量,这是 IMO 的好习惯)。

阶乘的一般问题是,它们很容易生成非常大的数字。您可以使用浮点数,从而牺牲精度但避免整数溢出问题。

哦等等,根据我上面写的,你应该把它设为一个无符号浮点数;-)

于 2008-10-25T12:50:20.183 回答
-3

如果我没记错的话:

无符号短整数 = 最大值 65535

无符号整数 = 最大值 4294967295

无符号长 = 最大值 4294967295

unsigned long long (Int64)= max 18446744073709551615

编辑来源:

Int/Long 最大值

现代编译器变量

于 2008-10-25T12:42:38.393 回答