引用here和here ...为什么我会在epsilon方法上使用二进制补码?对于大多数情况,epsilon 方法似乎已经足够了。
更新: 我纯粹是在寻找一个理论上的原因,为什么你会使用一个而不是另一个。我一直使用 epsilon 方法。
有没有人成功使用 2 的补码比较?为什么?为什么不?
您引用的第二个链接提到了一篇对该问题的描述很长的文章:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
但除非您正在调整性能,否则我会坚持使用 epsilon,以便人们可以调试您的代码
简而言之,在比较两个来源未知的浮点数时,选择一个有效的 epsilon 几乎是不可能的。
例如:
比较亚特兰大佐治亚州、达拉斯德克萨斯州和俄亥俄州某个地方之间的距离(以英里为单位)时,好的 epsilon 是多少?
在比较我的左脚、右脚和我桌子下的电脑之间的距离(以英里为单位)时,什么是好的 epsilon?
编辑:
好吧,我让相当多的人不明白为什么你不知道你的 epsilon 是什么。
回到过去,我编写了两个与 NeverWinter Nights(由 BioWare 制作的游戏)配合使用的程序。其中一个程序采用二进制模型并将其转换为 ASCII。另一个程序采用 ASCII 模型并将其编译为二进制。我编写的测试之一是获取 BioWare 的所有二进制模型,将它们反编译为 ASCII,然后再返回二进制。然后我将我的二进制版本与 BioWare 的原始版本进行了比较。比较期间的问题之一是处理浮点值的一些细微差异。因此,我不想为每种类型的浮点数(顶点、法线等)提出一堆不同的 EPSILONS,而是想使用诸如这两个恭维比较之类的东西。从而避免了整个多重 EPSILON 问题。
相同类型的问题可能适用于处理第 3 方数据的任何类型的软件,然后需要使用原始数据验证其结果。在这些情况下,您甚至可能不知道浮点值代表什么,您只需要比较它们即可。我们的工业自动化软件遇到了这个问题。
编辑:
大声笑,这已经被不同的人投票了。
我将问题归结为这个,给定两个任意浮点数,你如何决定使用什么 epsilon?你不能。
您如何将 1e23 和 1.0001e23 与 epsilon 进行比较,并且仍然使用相同的 epsilon 比较 1e-23 和 5.2e-23?当然,你可以做一些动态的 epsilon 技巧,但这就是整数比较的重点(它不需要整数是精确的)。
整数比较能够使用相对于数字大小的 epsilon 来比较两个浮点数。
编辑
史蒂夫,让我们看看你在评论中所说的话:
“但你知道平等对你意味着什么……因此,你应该能够找到一个合适的 epsilon”。
把这句话反过来说:
“如果你知道平等对你意味着什么,那么你应该能够找到一个合适的 epsilon。”
我想说的是,在某些应用程序中,我们不知道绝对意义上的相等意味着什么,因此我们必须求助于整数版本试图做的相对比较。
bits 方法可能更快。我说可能是因为在现代(多核、高度流水线)处理器上,通常不可能猜出真正更快的处理器。编码最简单最明显正确的实现,然后测量,然后优化。
在速度方面,请遵循以下规则:
做最简单的方法。
亚历克斯
奥斯卡是对的。除非你真的非常需要这种性能,否则不要搞砸。
而你没有。如果你处于这种情况,你就不需要问这个问题——你已经知道了。如果你认为你会,那么你不会。您的性能问题在其他地方。只需使用可读版本。
当分数由近似值表示时,使用任何按位比较的方法都会导致麻烦。所有浮点数的分数不是以 2 的幂(1/2、1/4、1/8、1/65536 和 c)命名的。所以,当然,都是无理数。
浮动第三 = 1/3; 浮动二=2.0;浮动另一个_两个=第三个*6.0;if(two != another_two) print ("近似值!\n");
唯一可以按位比较的情况是当您以完全相同的方式导出浮点数或者它们是精确表示(整数,2 的分数幂)时。即使那样,某些数字也可以有多种表示形式,尽管我从未在工作系统中看到过这种情况。