简体   繁体   English

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

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

Referenced here and here ...Why would I use two's complement over an epsilon method? 这里这里引用...为什么我会使用两个补码而不是epsilon方法? It seems like the epsilon method would be good enough for most cases. 对于大多数情况来说,似乎epsilon方法足够好。


Update: I'm purely looking for a theoretical reason why you'd use one over the other. 更新:我纯粹在寻找理论上的理由,为什么你要使用一个而不是另一个。 I've always used the epsilon method. 我一直使用epsilon方法。

Has anyone used the 2's complement comparison successfully? 有没有人成功使用2的补码比较? Why? 为什么? Why Not? 为什么不?

the second link you reference mentions an article that has quite a long description of the issue: 您引用的第二个链接提到了一篇对该问题有相当长描述的文章:

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

but unless you are tweaking performance I would stick with epsilon so people can debug your code 但除非你调整性能,否则我会坚持使用epsilon,以便人们可以调试你的代码

In short, when comparing two floats with unknown origins, picking an epsilon that is valid is almost impossible. 简而言之,当比较具有未知来源的两个浮点数时,选择一个有效的epsilon几乎是不可能的。

For example: 例如:

What is a good epsilon when comparing distance in miles between Atlanta GA, Dallas TX and some place in Ohio? 比较亚特兰大GA,达拉斯德克萨斯州和俄亥俄州某些地方之间的英里距离时,有什么好的epsilon?

What is a good epsilon when comparing distance in miles between my left foot, my right foot and the computer under my desk? 在比较我的左脚,右脚和桌子下面的电脑之间的距离时,有什么好的epsilon?

EDIT: 编辑:

Ok, I'm getting a fair number of people not understanding why you wouldn't know what your epsilon is. 好吧,我让很多人不理解为什么你不知道你的epsilon是什么。

Back in the old days of lore, I wrote two programs that worked with NeverWinter Nights (a game made by BioWare). 回到过去的传说,我写了两个与NeverWinter Nights(由BioWare制作的游戏)合作的程序。 One of the programs took a binary model and converted it to ASCII. 其中一个程序采用二进制模型并将其转换为ASCII。 The other program took an ASCII model and compiled it into binary. 另一个程序采用ASCII模型并将其编译为二进制。 One of the tests I wrote was to take all of BioWare's binary models, decompile them to ASCII and then back to binary. 我写的其中一个测试是采用所有BioWare的二进制模型,将它们反编译为ASCII,然后再反转为二进制模型。 Then I compared my binary version with original one from BioWare. 然后我将我的二进制版本与BioWare的原始版本进行了比较。 One of the problems during the comparison was dealing with some of the slight variances in floating point values. 比较期间的一个问题是处理浮点值的一些轻微差异。 So instead of coming up with a bunch of different EPSILONS for each type of floating point number (vertex, normal, etc), I wanted to use something such as this twos compliment compare. 因此,我没有为每种类型的浮点数(顶点,法线等)提出一堆不同的EPSILONS,而是希望使用诸如此两个补码比较之类的东西。 Thus avoiding the whole multiple EPSILON issue. 从而避免了整个多重EPSILON问题。

The same type of issue can apply to any type of software that processes 3rd party data and then needs to validate their results with the original. 相同类型的问题可以应用于处理第三方数据的任何类型的软件,然后需要使用原始数据验证其结果。 In these cases you might not even know what the floating point values represent, you just have to compare them. 在这些情况下,您可能甚至不知道浮点值代表什么,您只需要比较它们。 We ran into this issue with our industrial automation software. 我们的工业自动化软件遇到了这个问题。

EDIT: 编辑:

LOL, this has been voted up and down by different people. 大声笑,这是由不同的人投票上下。

I'll boil the problem down to this, given two arbitrary floating point numbers, how do you decide what epsilon to use? 我将问题归结为此,给定两个任意浮点数,你如何决定使用什么epsilon? You can't. 你不能。

How can you compare 1e23 and 1.0001e23 with an epsilon and still compare 1e-23 and 5.2e-23 using the same epsilon? 如何将1e23和1.0001e23与epsilon进行比较,仍然使用相同的epsilon比较1e-23和5.2e-23? Sure, you can do some dynamic epsilon tricks, but that is the whole point to the integer compare (which does NOT require the integers be exact). 当然,你可以做一些动态的epsilon技巧,但这是整数比较的整点(不要求整数是精确的)。

The integer compare is able to compare two floats using an epsilon relative to the magnitude of the numbers. 整数比较能够使用epsilon比较两个浮点数相对于数字的大小。

EDIT 编辑

Steve, lets look at what you said in the comments: 史蒂夫,让我们看看你在评论中说的话:

"But you know what equality means to you... Hence, you should be able to find an appropriate epsilon". “但你知道平等对你意味着什么......因此,你应该能够找到一个合适的epsilon”。

Turn this statement around to say: 把这句话说成:

"If you know what equality means to you, then you should be able to find an appropriate epsilon." “如果你知道平等对你意味着什么,那么你应该能够找到一个合适的epsilon。”

The whole point to what I am trying to say is that there are applications where we don't know what equality means in the absolute sense, thus we have to resort to a relative compare which is what the integer version is trying to do. 我要说的是,有些应用程序我们不知道绝对意义上的平等意味着什么,因此我们不得不求助于相对比较,即整数版本试图做的事情。

The bits method might be faster. 位方法可能更快。 I say might because on modern (multicore, highly pipelined) processors it is often impossible to guess what is really faster. 我说可能因为在现代(多核,高流水线)处理器上,通常不可能猜出什么是真正的更快。 Code the simplest most obviously correct implementation, then measure, then optomise. 编码最简单,最明显正确的实现,然后测量,然后进行光学测量。

When it comes to speed, follow these rules: 谈到速度,请遵循以下规则:

  1. If you're not a very experienced developer, don't optimize. 如果您不是一位经验丰富的开发人员,请不要进行优化。
  2. If you are an experienced developer, don't optimize yet. 如果您是经验丰富的开发人员,请不要进行优化。

Do the easiest method. 做最简单的方法。

Alex 亚历克斯

Oskar's right. 奥斯卡的权利。 Don't screw with this unless you really, really need that performance. 除非你真的需要这种表现,否则不要搞砸。

And you don't. 而你没有。 If you were in the situation that did, you wouldn't have needed to ask the question -- you'd already know. 如果你处于这样的情况,你就不需要问这个问题 - 你已经知道了。 If you think you do, then you don't. 如果你认为你这样做,那么你就不这样做。 Your performance problems lie elsewhere. 你的表现问题在别处。 Just use the readable version. 只需使用可读版本。

Using any method that compares bitwise will result in trouble when fractions are represented by approximations. 使用任何按位比较的方法将导致分数由近似表示时出现问题。 All floating point numbers with fractions that are not denominated in powers of two (1/2, 1/4, 1/8, 1/65536, &c) are approximated. 所有具有未以2的幂(1 / 2,1 / 4,1 / 8,1 / 65536和c)命名的分数的浮点数都是近似的。 So, of course, are all irrational numbers. 所以,当然,都是非理性的数字。

float third = 1/3; float third = 1/3; float two=2.0; 浮动二= 2.0; float another_two=third*6.0; float another_two = third * 6.0; if(two != another_two) print ("Approximation!\\n"); if(two!= another_two)print(“Approximation!\\ n”);

The only time comparing bitwise would work is when you derive the floating point numbers exactly the same way or they are exact representations (whole numbers, fraction powers of two). 唯一比较按位的方法就是当你以完全相同的方式得出浮点数时,或者它们是精确的表示(整数,分数幂为2)。 Even then, there can be multiple representations of some numbers, though I have never seen this in a working system. 即使这样,也可能存在多个数字的表示,尽管我从未在工作系统中看到过这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM