C:为什么不得到我输出的最后一行?

时间:2018-12-12 05:08:45

标签: c

我正在处理的问题要求我编写代码,将每个值从-1打印到1 ,并以0.01的值递增到求解数学函数f(x) = x^2 + 4(到小数点后4位)。

示例:

f(-1.00) = 5.0000
f(-0.99) = 4.9801
...
f(1.00) = 5.0000

问题:

我没有得到代码的最后一行:f(1.00) = 5.0000。我的问题是我如何修改程序使其显示出来,请问您为什么还没有显示它呢?

代码:

下面是我的代码。当yx0之间时,它将打印1的每个值,除了f(1.00) = 5.0000 ...

double numberForQ4 = -1.00; 
double valueOfY = 0; 

for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01 ) { 
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.2f) = %.4f \n", numberForQ4, valueOfY );
}

6 个答案:

答案 0 :(得分:4)

  

为什么没有得到我输出的最后一行?

由于0.01不能精确地表示为double,因为它编码为某些 binary 分数,所以浮点数学具有特殊性。在OP的情况下,高于或低于0.01的数值以及随后的数学运算仅会稍微产生意外结果。

  

如何修改程序

相反,使用整数进行迭代。

// for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01 ) { 
for ( int i = -100; i <= 100; i++ ) { 
  numberForQ4 = i/100.0;
  ...

提示:iteration循环最好使用整数进行编码。


  

您能否也解释一下为什么它不首先出现,   好吗?

再次尝试使用原始代码,并使用足够的精度查看原因。

printf( ".01 = %.21f\n", 0.01);
for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01 ) { 
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.21f) = %.21f \n", numberForQ4, valueOfY );
}

答案 1 :(得分:3)

如果您进行了一些小的更改:

for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01 ) { 
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.20f) = %.4f \n", numberForQ4, valueOfY );
         //       ^ 20 instead of 2
}

您将得到如下输出:

f(-1.00000000000000000000) = 5.0000 
f(-0.98999999999999999112) = 4.9801 
f(-0.97999999999999998224) = 4.9604 
f(-0.96999999999999997335) = 4.9409 
. . .
. . .
f(0.97000000000000141664) = 4.9409 
f(0.98000000000000142553) = 4.9604 
f(0.99000000000000143441) = 4.9801 

如您所见,双精度舍入误差导致“最后一次”迭代被跳过。也就是说:将0.1添加到0.99000000000000143441会得到大于1.0的值,从而导致循环结束。

有关解决此问题的方法,请参见@chux的答案:https://stackoverflow.com/a/53736875/4386427

答案 2 :(得分:1)

未获得最后一个值的原因与您正在使用的变量类型有关(双精度)。当您将索引变量增加0.1时,它并没有达到您期望的精确度。您可以通过下面的代码观察该值。

    int main()
{
    double numberForQ4 = -1.00; 
    double valueOfY = 0; 

    for ( ; numberForQ4 <= 1.00; numberForQ4 += 0.01) {
    printf("numForQ4 =  %.5f \n", &numberForQ4);
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.2f) = %.4f \n", numberForQ4, valueOfY );
    }

    return 0;
}

您会注意到最后一次呼叫是通过numberForQ4 = 0.98进行的。这就是为什么您无法使用1.00计算值的原因。

When you update your code line where you initilize variables to as shown below, you will get the correct output as I did in the online compiler. 



int main()
{
    float numberForQ4 = 1.00; 
    double valueOfY = 0; 

    for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.0100 ) {
    printf("numForQ4 =  %.5f\n", &numberForQ4);
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.2f) = %.4f \n", numberForQ4, valueOfY );
    }

    return 0;
}

答案 3 :(得分:0)

double numberForQ4 = 1.00; 
double valueOfY = 0; 

for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01 ) { 
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.2f) = %.4f \n", numberForQ4, valueOfY );
}

我猜你是要在numberForQ4的分配中输入-1.00或0

答案 4 :(得分:0)

更改为:

double numberForQ4; 
double valueOfY = 0; 
int i=0;


for ( numberForQ4 = -1.00; i <= 200; numberForQ4 += 0.01 , i++ ) { 
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.2f) = %.4f \n", numberForQ4, valueOfY );
}

您的旧循环从1.00开始并在1.00结束,因此它将仅执行一次迭代。 循环停止的条件是!(numberForQ4 <= 1.00),如果从1.00开始,则在下一次迭代中,numberForQ4将等于1.01(numberForQ4> 1.00)

您的计数器不够精确,注释中提到的最佳解决方案是使用整数计数器。

答案 5 :(得分:0)

增量为0.01,但由于float / double precision的工作方式,它可能不会与numberForQ4恰好相加0.01(因为在这里0.01不能确定它是float还是double,因为double只是float的精确度。) 在以下值的末尾

附加 f 会有所帮助

numberForQ4 += 0.01f

for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01f ) {

以下内容很好地介绍了这些舍入错误 http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)FloatingPoint.html