-nan返回值/ e(euler)被提升到功率计算循环

时间:2018-03-10 16:12:35

标签: c math while-loop factorial

我正在学习C编程并使用下面的算法来解决这个问题:

Link to a pic of the problem. 代码实际上有效,但最初循环只有10次重复(rep< = 10),而p = 3的anwer几乎是正确的,所以我改变了代表< = 20.而它给了我一个确切的答案从我的计算器。然后我尝试使用更高的数字12,输出再次是不准确的。所以我结束了提升rep< = 35.如果我得到更高重复的循环,我得到“-nan”,如果p的输入太高,它将是相同的。所以只需要看模式就知道不准确的问题会回来,因为我输入更高的数字而不是这种情况,因为如果我输入一个高值,输出将是NaN。

没有更高级别的功能可以解决它吗?只是想知道我的程序是否适合我现在的级别......

#include <stdio.h>

int main()
{
    float p; //the power for e
    float power; //the copy of p for the loop
    float e = 1; //the e number I wanna raise to the power of p
    int x = 1; //the starting number for each factorial generation
    float factorial = 1;
    int rep = 1; //the repeater for the loop

    printf( "Enter the power you want to raise: " );
    scanf( "%f", &p );

    power = p;

    while ( rep <= 35) {
        while ( x > 1) {
            factorial *= x;
            x--;
        }
        e += p / factorial;

        //printf("\nthe value of p: %f", p); (TESTER)
        //printf("\nthe value of factorial: %f", factorial); (TESTER)

        p *= power; //the new value for p
        rep++;
        factorial = 1;
        x = rep; //the new value for the next factorial to be generated

        //printf("\n%f", e); (TESTER)
    }
    printf("%.3f", e);

    return 0;
}

很抱歉,如果我有语法/拼写错误,我还在学习这门语言。

1 个答案:

答案 0 :(得分:1)

在开始之前,让我们将原始代码编写为函数,并进行一些清理:

float exp_original(float x, int rep = 35)
{
   float sum = 1.0f;
   float power = 1.0f;
   for (int i = 1; i <= rep; i++)
   {
      float factorial = 1.0f;
      for (int j = 2; j <= i; j++)
         factorial *= j;
      power *= x;
      sum += power / factorial;
   }
   return sum;
}

你使用的一些不必要的变量被删除了,但是其他程序是相同的:从头开始计算阶乘。

让我们看看系列中连续术语之间的比例:

enter image description here

因此,我们可以简单地将当前术语乘以此表达式,以获得 next 术语:

float exp_iterative(float x, int rep = 35)
{
   float sum = 1.0f;
   float term = 1.0f;
   for (int i = 1; i <= rep; i++)
   {
      term *= x / i;
      sum += term;
   }
   return sum;
}

似乎更简单,但它更好吗?与C库exp函数(我们假设最精确)的比较:

x   exp (C)       exp_orig    exp_iter
-------------------------------------------
1   2.7182817     2.718282    2.718282
2   7.3890562     7.3890567   7.3890567
3   20.085537     20.085539   20.085539
4   54.598148     54.598152   54.598152
5   148.41316     148.41318   148.41316
6   403.4288      403.42871   403.42877
7   1096.6332     1096.6334   1096.6334
8   2980.958      2980.9583   2980.9587
9   8103.084      8103.083    8103.083
10  22026.465     22026.467   22026.465
11  59874.141     59874.148   59874.152
12  162754.8      162754.77   162754.78
13  442413.41     -nan(ind)   442413.38
14  1202604.3     -nan(ind)   1202603.5
15  3269017.3     -nan(ind)   3269007.3
16  8886111       -nan(ind)   8886009
17  24154952      -nan(ind)   24153986
18  65659968      -nan(ind)   65652048
19  1.784823e+08   -nan(ind)  1.7842389e+08
20  4.8516518e+08  -nan(ind)  4.8477536e+08

这两个自定义实现在精确度方面是领先的,直到 x = 13,其中原始提供NaN。这是因为最高权力项13^35 = 9.7278604e+38超过了最大值FLT_MAX = 3.40282e+38。迭代版本中的累计术语永远不会达到接近极限的任何地方。