在MATLAB中减去两个相等的浮点数不等于0

时间:2016-03-18 17:53:11

标签: matlab floating-point precision

假设我们想以两种不同的方式计算(a + b) 2 ,即

  1. (a + b)*(a + b)

  2. a 2 + 2 a b + b 2

  3. 现在,假设b = -2.7format long。如果我们使用1.690000000000001在公式中插入这两个数字,我们会在a = 1.4; b = -2.7; format long r = (a + b) * (a + b) r2 = a^2 + 2*a*b + b^2 abs_diff = abs(r - r2) 两种情况下获得,也就是说,如果我运行以下脚本:

    r = 1.690000000000001
    
    r2 = 1.690000000000001
    
    abs_diff = 6.661338147750939e-16
    

    我获得了

    r

    这里发生了什么?我可以预览r2r的不同结果(因为Matlab将执行不同的浮点运算),但不能预测它们差异的绝对值。

    我还注意到r2rel_err1 = abs(1.69 - r) / 1.69 rel_err2 = abs(1.69 - r2) / 1.69 的相对误差是不同的,也就是说,如果我这样做

    rel_err1 = 3.941620205769786e-16
    
    rel_err2 = 7.883240411539573e-16
    

    我获得了

    r

    这只会让我觉得r2实际上并不是eps / 2。有没有办法完全看到它们,如果它们真的不同?如果没有,发生了什么?

    此外,两个相对误差都不小于{{1}},这是否意味着发生溢出?如果是的话,在哪里?

    注意:这是一个特例。我知道我们正在处理浮点数和舍入错误。但是我希望通过这个例子来更好地理解它们。

2 个答案:

答案 0 :(得分:3)

不要依赖format long的输出来得出两个数字相等的结论......

a = 1.4;
b = -2.7
r1 = (a + b) * (a + b);
r2 = a^2 + 2*a*b + b^2;
r3 = (a+b)^2;

相反,您可以使用以下方法检查其十六进制表示:

>> num2hex([r1 r2 r3])
ans =
3ffb0a3d70a3d70d
3ffb0a3d70a3d710
3ffb0a3d70a3d70d

printf系列函数:

>> fprintf('%bx\n', r1, r2, r3)
3ffb0a3d70a3d70d
3ffb0a3d70a3d710
3ffb0a3d70a3d70d

甚至:

>> format hex
>> disp([r1; r2; r3])
   3ffb0a3d70a3d70d
   3ffb0a3d70a3d710
   3ffb0a3d70a3d70d

答案 1 :(得分:1)

Floating point arithmetic is not associative

虽然在数学上这两个是相等的,但它们不是浮点数学。

r = (a + b) * (a + b)

r2 = a^2 + 2*a*b + b^2

在浮点数学中执行的顺序操作非常相关。这就是为什么当你做浮点数学时你需要非常小心你的乘法/除法的顺序,特别是在使用非常大的数字和非常小的数字时。