我正在处理的问题要求我编写代码,将每个值从-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
。我的问题是我如何修改程序使其显示出来,请问您为什么还没有显示它呢?
代码:
下面是我的代码。当y
在x
和0
之间时,它将打印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 );
}
答案 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