【问题标题】:comparing 2 floating numbers in matlab比较matlab中的2个浮点数
【发布时间】:2021-12-13 20:44:04
【问题描述】:

在过去的几周里,我被 Matlab 中的浮点比较问题折磨着。

我的代码涉及大量a<bc<=d。 让我抓狂的是

dw = 0.001;
W1 = [0:dw:1];
W2 = [0:dw:1];

那么我们有

>>W1(418) = 0.417000000000000
>>W2(418) = 0.417000000000000
>>W1(418)>=W2(418)

ans =

  logical

   0

>>W2(418)>=W1(418)

ans =

  logical

   1

我目前处理这个问题的方法是定义一个错误术语eps0 = 10^(-15)。然后,每当我希望拥有a<=b 时,我都会使用a<=b+eps0

但我想知道是否有更通用的方法来解决这个问题? 我真的很感激!

【问题讨论】:

  • W1(418) == W2(418) 是真的。事实上,all(W1==W2) 也是如此。我看不出您的示例会如何,因为两个数组的构造相同。
  • @CrisLuengo 在我的 Matlab R2018a 中,W1(418)==W2(418) 返回 false。也许 Matlab 在以后的版本中解决了这个问题?
  • @CrisLuengo 还是计算机硬件不同造成的?
  • 我今天早些时候在 MATLAB 在线(在 Linux 上运行的 R2021b)中尝试了这个。我在 macOS 上运行 R2017a 和 R2018b,我看到 all(W1==W2) 在两者中都返回 true。如果~all(W1==W2) 的唯一解释是W1W2 以不同的方式计算。每次您使用相同的输入运行相同的代码时,计算机都应该做完全相同的事情。硬件不可能改变这个结果,除非硬件有缺陷。但如果你有这样的缺陷,你早就注意到了。

标签: matlab floating-point floating-accuracy


【解决方案1】:

这就是你告诉我们你所做的,并且在我的 R2018a 版本中一切都按预期进行:

>> version
ans =
'9.4.0.813654 (R2018a)'
>> dw = 0.001;
>> W1 = [0:dw:1];
>> W2 = [0:dw:1];
>> W1(418)>=W2(418)
ans =
  logical
   1
>> W1(418) = 0.417000000000000;
>> W2(418) = 0.417000000000000;
>> W1(418)>=W2(418)
ans =
  logical
   1
>> W2(418)>=W1(418)
ans =
  logical
   1

所以我强烈怀疑还有一些你没有告诉我们的事情。我可以看到获得结果的一种方法是,如果基础向量的类型不同,那么 0.417 的分配就会以不同的方式转换。例如,假设 W1 实际上是单类型而不是双类型。然后你会得到这个结果:

>> dw = 0.001;
>> W1 = single([0:dw:1]);
>> W2 = [0:dw:1];
>> W1(418) = 0.417000000000000; % converted to closest SINGLE PRECISION bit pattern
>> W2(418) = 0.417000000000000; % converted to closest DOUBLE PRECISION bit pattern
>> W1(418)>=W2(418)
ans =
  logical
   0
>> W2(418)>=W1(418)
ans =
  logical
   1
>> sprintf('%.60f\n',W1(418))
ans =
    '0.416999995708465576171875000000000000000000000000000000000000
     '
>> sprintf('%.60f\n',W2(418))
ans =
    '0.416999999999999981792342396147432737052440643310546875000000
     '

所以这里的两个数字 W1(418) 和 W2(418) 实际上是不同的,因为一个存储为单精度浮点数,另一个存储为双精度浮点数。并且将 0.417 转换为二进制 IEEE 浮点位模式在两者之间有所不同。结果表明,单位模式的价值略低于双位模式,结果完全可以解释。

那么……你的 W1 和 W2 向量实际上是不同的类型吗?我怀疑他们是,这会质疑你所有的比较逻辑。正如其他人已经指出的那样,浮点运算结果通常必须谨慎对待,并且要非常仔细地进行比较(包括公差等)。

【讨论】:

    【解决方案2】:

    不,没有通用的方法来解决浮点数比较,每种情况都不一样,预期的舍入误差会随着情况而变化。

    不要使用eps0 = 10^(-15),而是使用eps(b)a<=b+eps(b)b+eps(b) 是下一个可以表示的较大值(假设 b 是正数)。这应该注意一种形式的舍入误差。如果舍入误差累积,您需要更大的边距:例如a<=b+10*eps(b)

    【讨论】:

    • 小心地认为 b+eps(b) 是下一个可表示的数字。对于 2 的负幂,它将跳过一个可表示的数字。例如,对于 IEEE-754 双精度二进制格式,-1 的 ULP 为 2^-52,但 -1+2^-53 是可表示的。
    • @EricPostpischil 这是一个非常好的观点,谢谢!
    猜你喜欢
    • 2011-08-24
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多