用于计算阶乘的C程序

abh*_*m93 3 c math recursion

我编写了一个小函数,用于计算C中数字的阶乘,如下所示:

int factNnumbers(int n)
{
    if(n == 1)
        return 1;
    else
        return (n*factNnumbers(--n));
}
Run Code Online (Sandbox Code Playgroud)

我将上面显示的函数称为:

factNnumbers(takeInputN());
Run Code Online (Sandbox Code Playgroud)

其中input(takeInputN)的函数定义为:

int takeInputN()
{   
    int n;
    printf("\n\nHow many numbers ?? \n ");
    scanf("%d", &n);
    return n;
}
Run Code Online (Sandbox Code Playgroud)

如果我在我的阶乘代码中更改一行,如下所示,我的程序运行完美.否则使用上面的代码打印数字输入的阶乘-1(例如,如果数字输入是5,它将打印阶乘4).为什么会这样?

int factNnumbers(int n)
{
    if(n != 1)
        return (n * factNnumbers(--n));
}
Run Code Online (Sandbox Code Playgroud)

kam*_*aze 6

您正在调用未定义的行为,它在一个版本中工作只是一个意外:

return (n*factNnumbers(--n));
Run Code Online (Sandbox Code Playgroud)

你首先使用n然后减少它还是相反?我不知道,编译器也没有,它可以自由地执行其中任何一个或格式化您的硬盘驱动器.只是用n * f(n - 1).

此外,您的"工作"版本不会返回该n==1案件,这是非法的.

  • 我不知道谁在这里讨价还价,但这是正确的答案. (3认同)

Rei*_*ica 6

问题是你n在同一个表达式中阅读和修改:

n * factNumbers(--n)
Run Code Online (Sandbox Code Playgroud)

对子表达式的n参数*--n子表达式的评估是无序的,它为您的代码提供了未定义的行为.

最简单的解决方案(以及IMO,更具表现力),就是说n - 1你的意思:

n * factNumbers(n - 1)
Run Code Online (Sandbox Code Playgroud)

问题底部的"改进"代码实际上更加错误.在那里,你有一个控制路径,它将返回一个未指定的值:一个明确的禁止.


注意:这个答案是在问题仍然具有C++标记时编写的,并使用C++术语.C中的最终效果是相同的,但术语可能不同.