MATLAB语言要注意浮点的不准确性

示例

浮点数不能代表所有实数。这就是所谓的浮点误差。

有无数个浮点数,它们可以无限长(例如π),因此要完美表示它们将需要无限量的内存。看到这是一个问题,因此设计了一种用于计算机中“实数”存储的特殊表示形式,即IEEE 754标准。简而言之,它描述了计算机如何以指数和尾数形式存储此类数字,例如,

floatnum = sign * 2^exponent * mantissa

对于这些位中的每一个,只有有限的位数,才能达到有限的精度。数字越小,可能的数字之间的距离越小(反之亦然!)。您可以在此在线演示中尝试您的真实数字。

请注意此行为,并尝试避免所有浮点数比较以及将其用作循环中的停止条件。请参阅以下两个示例:

示例:浮点比较完成WRONG:

>> 0.1 + 0.1 + 0.1  == 0.3

ans =

  logical

   0

如前例所示,使用浮点比较是不明智的做法。您可以通过取其差异的绝对值并将其与(较小)公差级别进行比较来克服它。

下面是另一个示例,其中在while循环中将浮点数用作停止条件:**

k = 0.1;
while k <= 0.3 
  disp(num2str(k));
  k = k + 0.1;
end

% --- Output: ---
0.1
0.2

它错过了最后一个预期的循环(0.3 <= 0.3)。

示例:浮点比较完成了:

x = 0.1 + 0.1 + 0.1;
y = 0.3;
tolerance = 1e-10; % A "good enough" tolerance for this case.

if ( abs( x - y ) <= tolerance )
  disp('x == y');
else
  disp('x ~= y');
end

% --- Output: ---
x == y

需要注意的几件事:

  • 正如预期的那样,现在x和y被视为等效。

  • 在上面的示例中,公差的选择是任意进行的。因此,选择的值可能不适用于所有情况(尤其是使用小得多的数字时)。可以使用函数(即,其中是一些特定于问题的数字)来智能地选择界限。对的合理选择也是允许的(即使在上述问题中也足够了)。epsN*eps(max(x,y))NN1E2N=1

进一步阅读:

有关浮点错误的更多信息,请参见以下问题:

  • 为什么在MATLAB中24.0000不等于24.0000?

  • 浮点数学运算是否被破坏?