为什么我要使用 2 的补码来比较两个双精度数,而不是将它们的差异与 epsilon 值进行比较?

StackOverflow https://stackoverflow.com/questions/96233

  •  01-07-2019
  •  | 
  •  

参考 这里这里...为什么我要使用补码而不是 epsilon 方法?看起来 epsilon 方法对于大多数情况来说已经足够了。


更新: 我纯粹是在寻找一个理论上的原因,说明为什么你会使用其中一种而不是另一种。我一直使用 epsilon 方法。

有人成功使用2的补码比较吗?为什么?为什么不?

有帮助吗?

解决方案

您引用的第二个链接提到了一篇文章,该文章对问题进行了相当长的描述:

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

但除非你正在调整性能,否则我会坚持使用 epsilon,这样人们就可以调试你的代码

其他提示

位方法可能更快。我说可能是因为在现代(多核、高度流水线)处理器上,通常不可能猜测什么是真正更快的。编写最简单、最明显正确的实现,然后测量,然后优化。

简而言之,当比较两个来源不明的浮点数时,选择有效的 epsilon 几乎是不可能的。

例如:

比较佐治亚州亚特兰大、德克萨斯州达拉斯和俄亥俄州某个地方之间的英里距离时,合适的 epsilon 是多少?

当比较我的左脚、右脚和桌子下面的电脑之间的距离(以英里为单位)时,合适的 epsilon 是多少?

编辑:

好吧,我发现很多人不明白为什么你不知道你的 epsilon 是什么。

回到传说的旧时代,我编写了两个与《无冬之夜》(BioWare 制作的游戏)配合使用的程序。其中一个程序采用二进制模型并将其转换为 ASCII。另一个程序采用 ASCII 模型并将其编译为二进制。我编写的测试之一是获取 BioWare 的所有二进制模型,将它们反编译为 ASCII,然后再恢复为二进制。然后我将我的二进制版本与 BioWare 的原始版本进行了比较。比较过程中的问题之一是处理浮点值的一些细微差异。因此,我不想为每种类型的浮点数(顶点、法线等)提供一堆不同的 EPSILONS,而是想使用诸如这种二进制补码比较之类的东西。从而避免了整个多重 EPSILON 问题。

相同类型的问题可能适用于处理第三方数据然后需要用原始数据验证其结果的任何类型的软件。在这些情况下,您甚至可能不知道浮点值代表什么,您只需比较它们即可。我们的工业自动化软件遇到了这个问题。

编辑:

哈哈,这已经被不同的人投票赞成和反对。

我将把问题归结为这个,给定两个 随意的 浮点数,你如何决定使用什么epsilon?你不能。

如何将 1e23 和 1.0001e23 与 epsilon 进行比较,同时仍然使用相同的 epsilon 来比较 1e-23 和 5.2e-23?当然,您可以执行一些动态 epsilon 技巧,但这就是整数比较的全部意义(不需要整数精确)。

整数比较能够使用相对于数字大小的 epsilon 来比较两个浮点数。

编辑

史蒂夫,让我们看看你在评论中说的话:

“但你知道平等对你意味着什么......因此,您应该能够找到合适的 epsilon”。

把这句话反过来说:

“如果你知道平等对你意味着什么,那么你应该能够找到合适的 epsilon。”

我想说的重点是,在某些应用程序中,我们不知道绝对意义上的相等意味着什么,因此我们必须诉诸相对比较,这就是整数版本试图做的事情。

当谈到速度时,请遵循以下规则:

  1. 如果您不是经验丰富的开发人员,请不要优化。
  2. 如果您是经验丰富的开发人员,请不要进行优化。

做最简单的方法。

亚历克斯

奥斯卡是对的。除非你真的非常需要这种性能,否则不要搞砸这个。

而你却没有。如果你处于这种情况,你就不需要问这个问题了——你已经知道了。如果您认为您这样做,那么您就不会。您的性能问题出在其他地方。只需使用可读版本即可。

当分数用近似值表示时,使用任何按位比较的方法都会导致麻烦。所有带有不以 2 的幂表示的分数的浮点数(1/2、1/4、1/8、1/65536 等)均经过近似计算。当然,所有无理数也是如此。

浮点第三= 1/3;浮点二=2.0;浮点数 another_two=third*6.0;if(二!=另一个_two)print(“近似! n”);

按位比较唯一有效的时候是当您以完全相同的方式导出浮点数或者它们是精确表示形式(整数、2 的分数幂)时。即使如此,某些数字也可以有多种表示形式,尽管我从未在工作系统中见过这种情况。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top