注意浮点不准确

浮点数不能代表所有实数。这称为浮点不准确。

存在无限多个浮点数并且它们可以无限长(例如,π),因此能够完美地表示它们将需要无限量的存储器。看到这是一个问题,设计了计算机中实数存储的特殊表示,即 IEEE 754 标准 。简而言之,它描述了计算机如何存储这种类型的数字,带有指数和尾数,如,

floatnum = sign * 2^exponent * mantissa

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

请注意此行为并尝试避免所有浮点比较以及它们在循环中用作停止条件。见下面的两个例子:

示例:完成浮点比较错误:

>> 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

有几点需要注意:

  • 正如所料,现在 xy 被视为等效。
  • 在上面的例子中,公差的选择是任意的。因此,所选择的值可能并不适合所有情况(特别是在使用小得多的数字时)。智能选择绑定可以使用 eps 函数完成,即 N*eps(max(x,y)),其中 N 是一些特定于问题的数字。对于 N 来说,合理的选择也是允许的,但是,即使在上面的问题中,N=1 也足够了。

进一步阅读:

有关浮点不准确的更多信息,请参阅以下问题: