简体   繁体   English

用于计算阶乘的C程序

[英]C program for calculating factorial

i have written a small function which calculates factorial for a number in C as follows: 我编写了一个小函数,用于计算C中数字的阶乘,如下所示:

int factNnumbers(int n)
{
    if(n == 1)
        return 1;
    else
        return (n*factNnumbers(--n));
}

I call the function shown above as: 我将上面显示的函数称为:

factNnumbers(takeInputN());

where the function to take the input ( takeInputN ) is defined as: 其中输入函数( takeInputN )定义为:

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

If I change one line in my factorial code as shown below , my program works perfectly. 如果我在我的阶乘代码中更改一行,如下所示,我的程序运行完美。 Otherwise with the above code it prints the factorial of the number input -1 (example if number input is 5 , it will print the factorial of 4 ). 否则使用上面的代码打印数字输入-1的阶乘(例如,如果数字输入为5 ,则打印阶乘4 )。 Why is this happening?. 为什么会这样?

int factNnumbers(int n)
{
    if(n != 1)
        return (n * factNnumbers(--n));
}

You are invoking undefined behaviour, that it works in one version is just an accident: 您正在调用未定义的行为,它在一个版本中工作只是一个意外:

return (n*factNnumbers(--n));

Do you use n first and then decrement it or the other way around? 你首先使用n然后递减它还是相反? I don't know and neither does the compiler, it's free to do either of them or format your hard drive. 我不知道,编译器也没有,它可以自由地执行其中任何一个或格式化您的硬盘驱动器。 Just use n * f(n - 1) . 只需使用n * f(n - 1)

Also, your "working" version does not return for the n==1 case, which is illegal. 此外,您的“工作”版本不会返回n==1情况,这是非法的。

The problem is that you're both reading and modifying n in the same expression: 问题是你在同一个表达式中读取和修改n

n * factNumbers(--n)

The evaluation of the n argument to * and of the --n subexpression are unsequenced, which gives your code Undefined Behaviour. 该评价n参数*和的--n子表达式是未测序,这使你的代码未定义行为。

The easiest solution (and also, IMO, more expressive), is to say n - 1 where you mean it: 最简单的解决方案(以及IMO,更具表现力),就是说n - 1你的意思是:

n * factNumbers(n - 1)

Your "improved" code in the bottom of the question is actually even more wrong. 问题底部的“改进”代码实际上更加错误。 There, you have a control path which will return an unspecified value: a clear no-no. 在那里,你有一个控制路径,它将返回一个未指定的值:一个明确的禁止。


Note: This answer was written while the question still had a C++ tag, and uses C++ terminology. 注意:这个答案是在问题仍然具有C ++标记时编写的,并使用C ++术语。 The end effect in C is the same, but the terminology might be different. C中的最终效果是相同的,但术语可能不同。

There are two causes of undefined behavior in your code: 代码中存在两种未定义行为的原因:

  1. Whether n or --n in n * factNnumbers(--n) will be evaluated first is unspecified. 首先评估n * factNnumbers(--n) n--n是否未指定。
    See this . 看到这个 You want just n * factNnumbers(n - 1) , why decrement? 你只需要n * factNnumbers(n - 1) ,为什么减少? You're not using decremented n afterwards (at least you didn't want to). 之后你没有使用减少的n (至少你不想这样)。

  2. You're not returning a value on all control paths, what's going to be returned on n == 1 ? 你没有在所有控制路径上返回一个值, n == 1会返回什么? An indeterminate value that will mess up the whole result. 一个不确定的值会弄乱整个结果。

the rule of decrement: X = Y-- first passes the value of I to X and decrements after X = --I first pass and decrements the value decremented X 递减规则:X = Y--首先将I的值传递给X并在X = - I第一次传递后递减并递减递减的值X

for your case, you decrement the value of parameter passed as argument to the function factNnumbers. 对于您的情况,您将作为参数传递的参数值递减到函数factNnumbers。 Therefore remedy this error, I invite you to put (n-1) instead of (--n). 因此纠正这个错误,我邀请你把(n-1)代替(--n)。

I think it's better to use the tgamma function from math.h for double precision calculations involving factorials (such as Poisson distribution etc.): tgamma(n+1) will give you factorial(n). 我认为最好使用math.h中的tgamma函数进行涉及阶乘的双精度计算(例如泊松分布等):tgamma(n + 1)将给出阶乘(n)。

Factorial function is increasing very fast, and this will work also for values too big to fit an integer type. 因子函数的增长非常快,这也适用于太大而不适合整数类型的值。

When n<=1 (or == 1 in your code), the factorial function has to return 1. Futhermore the your --n in you code is false and sould be n-1 as: 当n <= 1(或代码中= = 1)时,阶乘函数必须返回1.此外,您的代码中的--n为false,并且应为n-1,如下所示:

function factorial(n)
{
   if (n<=1)
      return 1;
   else
      return n * factorial(n-1);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM