2016-03-18 307 views
0

假设我们要计算(A + B)以两种不同的方式,即减去MATLAB两个相等的浮点数字不等于0

  1. (A + B)*( A + b)

  2. 一个 + 2 AB + b

现在,假设a = 1.4b = -2.7。如果我们在公式插上这两个数字与format 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 

这是怎么回事?我可以预览rr2的不同结果(因为Matlab将执行不同的浮点运算),但不能用于它们差异的绝对值。

我也注意到的rr2相对误差是不同的,也就是说,如果我做

rel_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

这可能是由于浮点错误依赖的事实ds在*订单*,*类型*和*号码*操作。你的两种方法有不同的操作数量和类型。 [更多添加理论上介绍](http://floating-point-gui.de/errors/propagation/)更多的浮点错误。另外更多的操作会导致更多的错误传播。 – Suever

+0

@Suever我的直觉是,因为两种方法实际上都是以不同的方式实现的,即使用不同的浮点运算,那么我们会得到不同的结果,并且这可以解释它们的差别不同于0(无论如何)。但是Matlab显然用相同的方式表示'r'和'r2',所以它们的差别应该是0 ... – nbro

+0

你的文章中的内容表明MATLAB用同样的方式表示'r'和'r2'? – Suever

回答

1

Floating point arithmetic is not associative

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

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

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

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

+0

好吧,但是如果'r'和'r2'显然在内存中代表相同的数字,它们的绝对值差异将等于零... – nbro

3

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

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

printf家庭的功能:

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

甚至:

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

相反,你可以通过检查其十六进制表示

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

如何使用'fprintf'打印一个有我们想要的十进制数字的浮点数字的建议,例如'fprintf('%。60f',my_float);' ? – nbro

+0

我会一直信任十六进制表示,因为这是实际的1和0的存储,不涉及四舍五入......更不用说,如果'my_float = realmin'例如用'fprintf'走多远? – Amro