在 MATLAB 中比较 2 个浮点数

comparing 2 floating numbers in matlab

提问人:kim kevin 提问时间:10/29/2021 更新时间:10/30/2021 访问量:433

问:

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

我的代码涉及大量的 or . 让我发疯的是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<=ba<=b+eps0

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

MATLAB 点浮 点精度

评论

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

答:

1赞 Cris Luengo 10/29/2021 #1

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

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

评论

2赞 Eric Postpischil 10/29/2021
不要认为 b+eps(b) 是下一个可表示的数字。对于 2 的负幂,它将跳过一个可表示的数字。例如,使用 IEEE-754 双精度二进制格式时,−1 的 ULP 为 2^−52,但 −1+2^−53 是可表示的。
0赞 Cris Luengo 10/29/2021
@EricPostpischil 这是一个很好的观点,谢谢!
0赞 James Tursa 10/30/2021 #2

这就是你告诉我们你所做的,在我的 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 向量实际上是不同的类型吗?我怀疑他们是,这让人质疑你所有的比较逻辑。正如其他人已经指出的那样,浮点算术结果通常必须持保留态度,并非常仔细地进行比较(公差等)。