有两个类似的matlab程序,一个迭代10次,另一个迭代11次。
一:
i = 0;
x = 0.0;
h = 0.1;
while x < 1.0
i = i + 1;
x = i * h;
disp([i,x]);
end
另:
i = 0;
x = 0.0;
h = 0.1;
while x < 1.0
i = i + 1;
x = x + h;
disp([i,x]);
end
我不明白为什么浮点添加操作和多重操作之间存在差异。
答案 0 :(得分:4)
使用浮点计数器进行迭代时,您应该非常小心。作为一个例子,我将告诉你在你的情况下发生了什么(这是一个Java程序,但你的情况应该是相同的):click here to run it yourself
double h = 0.1;
System.out.println(10*h-1.0);
System.out.println(h+h+h+h+h+h+h+h+h+h-1.0);
它只是在执行乘法与seprarate添加时将差异打印为1。
由于浮点数的表示不准确,结果如下所示:
0.0
-1.1102230246251565E-16
因此,如果在后一种情况下将其用作循环条件,则会有一个额外的迭代(尚未达到一个)。
尝试使用计数器变量i
这是一个整数,你不会遇到这样的问题。
答案 1 :(得分:2)
比较以下内容的输出:
>> fprintf('%0.20f\n', 0.1.*(1:10))
0.10000000000000001000
0.20000000000000001000
0.30000000000000004000
0.40000000000000002000
0.50000000000000000000
0.60000000000000009000
0.70000000000000007000
0.80000000000000004000
0.90000000000000002000
1.00000000000000000000
>> fprintf('%0.20f\n', cumsum(repmat(0.1,1,10)))
0.10000000000000001000
0.20000000000000001000
0.30000000000000004000
0.40000000000000002000
0.50000000000000000000
0.59999999999999998000
0.69999999999999996000
0.79999999999999993000
0.89999999999999991000
0.99999999999999989000
还要与使用MATLAB的COLON运算符进行比较:
>> fprintf('%0.20f\n', 0.1:0.1:1)
0.10000000000000001000
0.20000000000000001000
0.30000000000000004000
0.40000000000000002000
0.50000000000000000000
0.59999999999999998000
0.69999999999999996000
0.80000000000000004000
0.90000000000000002000
1.00000000000000000000
如果要查看64位二进制表示,请使用:
>> format hex
>> [(0.1:0.1:1)' (0.1.*(1:10))' cumsum(repmat(0.1,10,1))]
3fb999999999999a 3fb999999999999a 3fb999999999999a
3fc999999999999a 3fc999999999999a 3fc999999999999a
3fd3333333333334 3fd3333333333334 3fd3333333333334
3fd999999999999a 3fd999999999999a 3fd999999999999a
3fe0000000000000 3fe0000000000000 3fe0000000000000
3fe3333333333333 3fe3333333333334 3fe3333333333333
3fe6666666666666 3fe6666666666667 3fe6666666666666
3fe999999999999a 3fe999999999999a 3fe9999999999999
3feccccccccccccd 3feccccccccccccd 3feccccccccccccc
3ff0000000000000 3ff0000000000000 3fefffffffffffff
一些建议的读数(与MATLAB相关):
答案 2 :(得分:0)
浮点数的表示是精确的,除了浮点运算在基数2中,小数(如0.1)具有无限的二进制扩展。由于浮点数具有有限的位数,因此必须舍入0.1的无限扩展,并且在加法时累积误差累积,导致差异。
但是,大多数浮点操作都是不精确的:结果USUALLY需要比固定位数更多的精度位,因此CPU自动舍入结果以适应可用的精确。正如您所注意到的,这种舍入误差会累积在长计算链中,并导致实际与“正确”结果之间存在巨大差异。 (“正确”被定义为在无限精度算术中获得的结果。)