当我计算一个大的阶乘时,为什么我会得到一个负数



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

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"类,可能很合适!)而不会再次遇到这个问题?

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

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

你需要一个像这样的C++大数库。

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

  • 你对负数没有防备。
  • 的阶乘是 1,而不是零。

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

考虑使用大数库。他们中的许多人都在C++。

如果未指定有符号或无符号,则默认为签名。您可以使用编译器上的命令行开关对其进行修改。

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

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

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

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

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

哦,等等,根据我上面写的,你应该把它做成一个未签名的浮点;-)

如果我记得不错的话:

无符号短 int = 最大值 65535

无符号整数 = 最大4294967295

无符号长 = 最大4294967295

无符号长长 (Int64 )= 最大18446744073709551615

编辑来源:

整数/长最大值

现代编译器变量

相关内容

  • 没有找到相关文章

最新更新