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

时间:2020-03-06 14:23:12  来源:igfitidea点击:

为什么要在epsilon方法上使用二进制补码?在大多数情况下,epsilon方法似乎已经足够了。

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

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

解决方案

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

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

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

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

例如:

比较亚特兰大GA,德克萨斯州达拉斯市和俄亥俄州的某个地方之间的英里数时,什么是好的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相对于数字的大小来比较两个浮点数。

编辑

史蒂夫,让我们看看我们在评论中说了什么:

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

将此语句转过来说:

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

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

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

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

  • 如果我们不是经验丰富的开发人员,请不要进行优化。
  • 如果我们是经验丰富的开发人员,请不要进行优化。

做最简单的方法。

亚历克斯

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

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

当分数用近似值表示时,使用任何按位比较的方法都会造成麻烦。所有浮点数的分数均不以2的幂表示(1 / 2、1 / 4、1 / 8、1 / 65536和&c)。因此,当然都是无理数。

浮动三分之一= 1/3;
浮点数= 2.0;
float another_two = third * 6.0;
if(两个!= another_two)
打印("近似值!\ n");

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