使用迭代和递归计算阶乘时的不同答案

Different answers when calculating factorial using iteration and recursion

本文关键字:答案 阶乘 迭代 递归计算      更新时间:2023-10-16

第一次在这里发帖,我希望这个问题是可以接受的。

作为一个小测试,我编写了一个应用程序,使用迭代和递归计算一个数字的阶乘。除了试图计算大于24的数的阶乘外,这似乎工作得很好。

例如,当计算24的阶乘时,两种方法都给出了正确的答案62044840173323941。

然而,当计算25的阶乘时,答案不同。递归法的结果为1.5511210043330986e+025,迭代法的结果为1.5511210043330984e+025。

根据Wolfram Alpha,正确答案应该与迭代方法相同,那么为什么函数之间存在差异?我问了我的同事,他们也无法解释这种行为。

#define TEST_CASE 25
double GetFactorialRecursive(double i)
{   
    if (i == 1)
    return i;
    else
    return i * GetFactorialRecursive(i - 1);
}
double GetFactorialIterative(double i)
{
    double result = 1.0;
    for (; i > 0; --i)
        result *= i;
    return result;
}
int main ()
{
    double recres = 0, itrres = 0; 
    recres = GetFactorialRecursive(TEST_CASE);
    itrres = GetFactorialIterative(TEST_CASE);
    if (recres != itrres)
        std::cout << "Error" << "n";
    std::cout << std::setprecision(25) << "Recursion: " << recres << ", Iteration: " << itrres << "n";
    return 0;
}

谢谢您的考虑。

递归版本计算5 * (4 * (3 * (2 * 1)))

迭代版本计算1 * (2 * (3 * (4 * 5)))

操作顺序的不同会改变浮点运算的舍入方式,从而导致不同的结果。

类型double不是精确类型。它保证是正确值的近似值。

所以不能保证两种实现都是精确的

考虑到你的实现,有两个因素可能导致不同的答案。

  1. 你的乘法顺序不一样。
  2. 你的迭代版本在同一个变量中执行所有的数学运算。intel兼容的架构(x86和x86-64)在其浮点寄存器中使用80位精度,并且该精度一直保持到寄存器被存储到内存中。

由于浮点四舍五入,乘法的顺序不同,得到的结果也不同。

如果您将for循环从1变为i(而不是从i变为1),您应该得到与递归版本相同的结果。