计算阶乘> 31时如何处理整数溢出

时间:2019-02-11 12:39:43

标签: c factorial

迭代函数返回阶乘运算的结果。我尝试计算一个将导致整数溢出的数字后,代码似乎中断了。我该如何最好地处理呢?这是否有意义,是否准确?是将超过最大限制的每次迭代都存储为的幂,然后返回该限制以及一个字符串,该字符串描述可以自身乘以的次数?

int ft_iterative_factorial(int nb)
{
  int i;
  int n;
  int res;

  i = 1;
  n = nb;
  res = nb;
  while (i < nb)
  {
    if (nb == 1 || nb == 0)
    {
      res = 1;
      break ;
    }
    res = res * (n - 1);
    i++;
    n--;
  }
  return ((nb < 0 || nb > 31) ? 0 : res);
}

4 个答案:

答案 0 :(得分:3)

您的功能真的很复杂。

请考虑以下实施方式:

int ft_iterative_factorial(int nb)
{
  int res = 1;

  for (int i = 2; i <= nb; i++)
  {
    res = res * i;
  }

  return res;
}

您的测试return ( nb < 0 ? 0 : res);在循环后没有多大意义,您应该在循环前进行,if (nb == 1 || nb == 0)在循环内也没有意义。但是无论如何,这些测试对我的代码毫无意义。

int可能是32位类型,而32位不足以存储16位!。

要么使用long long(通常为64位)而不是int(但是限制为21左右),否则处理值大于16的情况。

顺便说一句:如果您真的想快点,不要计算阶乘,而要使用查找表,这是读者的练习。 / p>

答案 1 :(得分:1)

使用long long或尝试优化计算(如果可能)。

最后,一种替代方法是搜索大整数库。

答案 2 :(得分:1)

您正在使用有符号整数进行计算,并且有符号整数溢出是未定义的行为。因此,无论您的代码是什么,都可以根据C标准正确返回。通常会发生的是,您只是得到正确结果的低位比特。由于它是带符号的int,因此可以为负。

如果您只想获得大数的近似结果,那么为什么不更改代码以使用double?对于3之类的小数字!您仍然会得到6,但超过17则得到4.643 + E8,即4.643 * 10 ^ 8。双重类型最终将用完指数,但它比无符号长久还带给您更多的东西。

答案 3 :(得分:0)

对于有能力的最大阶乘,可以将此函数的返回类型使用unsigned long long。而且您的函数是递归样式,运行时间比非递归样式慢。 我认为这是一个很好的解决方案

unsigned long long ft_iterative_factorial(int nb)
{
    unsigned long long result = 1;

    for (int i = 2; i <= nb; i++)
    {
        result = result * (unsigned long long)i;
    }

    return result;
}

int main()
{
    cout << ft_iterative_factorial(17) << endl;
    return 0;
}