关于C#:为什么我要使用2的补数来比较两个双精度值,而不是将其差值与epsilon值进行比较?

关于C#:为什么我要使用2的补数来比较两个双精度值,而不是将其差值与epsilon值进行比较?

Why would I use 2's complement to compare two doubles instead of comparing their differences against an epsilon value?

这里和这里都引用过...为什么我要在epsilon方法上使用二进制补码?看来epsilon方法在大多数情况下已经足够了。

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

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


您引用的第二个链接提到了一篇对该问题有很长描述的文章:

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

但是除非您要调整性能,否则我会坚持使用epsilon,以便人们可以调试您的代码


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


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

例如:

比较亚特兰大GA,达拉斯和俄亥俄州的某个地方之间的英里数时,一个好的epsilon是什么?

比较左脚,右脚和书桌下的计算机之间的距离(以英里为单位),什么是好的epsilon?

编辑:

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

在过去的传说中,我编写了两个与NeverWinter Nights(由BioWare制作的游戏)配合使用的程序。其中一个程序采用了二进制模型,并将其转换为ASCII。另一个程序采用ASCII模型并将其编译为二进制。我编写的测试之一是采用BioWare的所有二进制模型,将它们反编译为ASCII,然后再恢复为二进制。然后,我将我的二进制版本与BioWare的原始版本进行了比较。比较期间的问题之一是处理浮点值的一些细微差异。因此,我没有为每种类型的浮点数(顶点,法线等)提出一堆不同的EPSILONS,而是想使用诸如此类的二进制补码比较。从而避免了整个多个EPSILON问题。

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

编辑:

大声笑,这是由不同的人上下投票的。

在给出两个任意浮点数的情况下,我将问题归结为这一点,您如何确定要使用的epsilon?你不能。

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

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

编辑

史蒂夫,让我们看看您在评论中所说的:

"但是您知道平等对您意味着什么……因此,您应该能够找到合适的epsilon "。

将此语句转过来说:

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

我要说的重点是,有些应用程序不知道绝对意义上的相等,因此我们必须求助于相对比较,这是整数版本正在尝试的要做。


使用任何按位比较的方法,当分数用近似值表示时,会造成麻烦。所有浮点数的分数均不以2(1 / 2、1 / 4、1 / 8、1 / 65536,


奥斯卡(Oskar)的权利。除非您真的非常需要这种性能,否则请不要为此烦恼。

而你没有。如果您处在这种情况下,那么您就不必问这个问题了-您已经知道了。如果您认为自己做得到,那你就不会做。您的性能问题在其他地方。只需使用可读版本。


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

  • 如果您不是经验丰富的开发人员,请不要进行优化。
  • 如果您是经验丰富的开发人员,请不要进行优化。
  • 执行最简单的方法。

    亚历克斯


    推荐阅读