Why doesn't infinity comparison follow the logic applied to NaNs? This code prints out false
three times:
为什么不进行无限大比较的逻辑应用于NaNs?此代码打印错误三次:
double a = Double.NaN;
double b = Double.NaN;
System.out.println(a == b); // false
System.out.println(a < b); // false
System.out.println(a > b); // false
However, if I change Double.NaN
to Double.POSITIVE_INFINITY
, I get true
for equality, but false
for the greater-than and less-than comparisons:
但是,如果我把它换成双倍。双南。正无穷,我对等式成立,但对大于和小于的比较成立:
double a = Double.POSITIVE_INFINITY;
double b = Double.POSITIVE_INFINITY;
System.out.println(a == b); // true
System.out.println(a < b); // false
System.out.println(a > b); // false
This seems dangerous. Assuming that infinite values result from overflows, I imagine it's more likely that two variables that ended up as infinities wouldn't actually be equal in perfect arithmetic.
这似乎是危险的。假设无限值是由超流产生的,我想两个最终成为不定式的变量在完美的算术中不可能是相等的。
8 个解决方案
#1
70
Your reasoning is that Double.POSITIVE_INFINITY
should not be equal to itself because it is “likely” to have been obtained as the result of a loss of accuracy.
你的推理是双重的。POSITIVE_INFINITY不应该等于它本身,因为它“可能”是由于失去了准确性而获得的。
This line of reasoning applies to all of floating-point. Any finite value can be obtained as the result of an inaccurate operation. That did not push the IEEE 754 standardization committee to define ==
as always evaluating to false for finite values, so why should infinities be different?
这种推理方法适用于所有浮点数。由于操作不准确,可以得到任何有限值。这并没有促使IEEE 754标准化委员会定义== =,因为对于有限的值,总是将其评估为false,那么为什么不定式应该是不同的呢?
As defined, ==
is useful for people who understand what it does (that is, test the floating-point values that have been obtained, and certainly not the values that should have been obtained with real computations). For anyone who understands that, and you need to understand it to use floating-point even for computations that do not involve infinity, having Double.POSITIVE_INFINITY == Double.POSITIVE_INFINITY
evaluate to true is convenient, if only to test if the floating-point result of a floating-point computation is Double.POSITIVE_INFINITY
.
如定义的那样,==对于理解它的功能的人是有用的(也就是说,测试已经获得的浮点值,而不是真正的计算应该获得的值)。对于任何理解这一点的人,你需要理解它使用浮点数,即使计算不涉及无穷,有两倍。POSITIVE_INFINITY = =翻倍。POSITIVE_INFINITY评估为true是很方便的,如果只是为了测试浮点计算的浮点结果是否为Double.POSITIVE_INFINITY。
That leaves the question of why NaN can afford to have special behavior, and infinities should follow the same general principles as finite values. NaN is different from infinities: the underlying principle of the IEEE 754 standard is that values are exactly what they are, but the result of an operation can be approximated with respect to the real result, and in this case, the resulting floating-point value is obtained according to the rounding mode.
这就留下了一个问题:为什么NaN能够承担得起特殊的行为,不定式应该遵循与有限值相同的一般原则。南不同于无穷大:IEEE 754标准的基本原则是,值是什么,但一个操作的结果可以近似对真正的结果,在这种情况下,产生的浮点值是根据获得的舍入模式。
Forget for an instant that 1.0 / 0.0
is defined as +inf, which is an annoyance in this discussion. Think for the moment of Double.POSITIVE_INFINITY
only as the result of operations such as 1.0e100 / 1.0e-300
or Double.MAX_VALUE + Double.MAX_VALUE
. For these operations, +inf is the closest approximation of the real result, just like for operations that produce a finite result. By contrast, NaN is the result you obtain when the operation doesn't make sense. It is defensible to have NaN behave specially, but inf is just an approximation of all the values too large to represent.
暂时忘记1.0 / 0.0被定义为+inf,这在本讨论中很烦人。想一下双重的时刻。只能进行1。0e100 / 1。0e-300或2。MAX_VALUE + Double.MAX_VALUE。对于这些操作,+inf是真实结果的最接近近似值,就像产生有限结果的操作一样。相反,NaN是当操作没有意义时得到的结果。让NaN有特殊行为是有道理的,但是inf只是所有值的近似值,这些值太大而无法表示。
In reality, 1.0 / 0.0
also produces +inf, but that should be considered an exception. It would have been just as coherent to define the result of that operation as NaN, but defining it as +inf was more convenient in the implementation of some algorithms. An example is provided page 10 in Kahan's notes. More details than most will wish for are in the article “Branch Cuts for Complex Elementary Functions, or Much Ado About Nothing's Sign Bit”. I would also interpret the existence in IEEE 754 of a “division by zero” flag separate from the NaN flag as recognition that the user may want to treat division by zero specially although it is not defined as producing NaN.
实际上,1.0 / 0.0也生成+inf,但这应该被视为一个例外。将该操作的结果定义为NaN应该和nf一样一致,但是将其定义为+inf在实现某些算法时更方便。在Kahan的笔记中提供了一个例子。比大多数人所希望的更详细的是在“复杂基本函数的分支削减,或关于无符号比特的麻烦”这篇文章中。我还将IEEE 754中“零除”标志与NaN标志分离的存在解释为用户可能希望通过0来处理除法,尽管它没有定义为生成NaN。
#2
6
Because thats the standard. Infinity represents a number greater than or less than Double.MAX_VALUE/-Double.MAX_VALUE.
因为这是标准的。无穷大表示大于或小于doubley . max_value /- doubley . max_value。
NaN represents the outcome of an operation that didn't make sense. That is, the operation didn't possibly come out with a number.
NaN代表了一个没有意义的操作的结果。也就是说,手术不可能得到一个数字。
I would guess the logic is once a number gets big enough (infinity) and because of the limitation of floating point numbers, adding numbers to it won't change the outcome, so its 'like' infinity.
我猜逻辑是,当一个数字变得足够大(无穷大)并且由于浮点数的限制,加上数字不会改变结果,所以它是“无穷大”。
So if you want to compare to really big numbers, at some point you might just say those two big numbers are close enough for all intents and purposes. But if you want to compare two things that both aren't numbers, you can't compare them so its false. At least you couldn't compare them as a primitive.
所以如果你想和真正的大数相比,在某种程度上你可能会说这两个大数足够接近于所有的意图和目的。但是如果你想比较两个都不是数字的东西,你不能比较它们,所以它是假的。至少你不能把它们和原始人相比。
#3
5
Why are infinities equal? Because it works.
为什么无穷大平等?因为它的工作原理。
Floating-point arithmetic is designed to produce (relatively) fast computations that preserve errors. The idea being that you don't check for overflows or other nonsense during a lengthy calculation; you wait until it's finished. That's why NaNs propagate the way they do: once you've gotten a NaN, there are very few things you can do that will make it go away. Once the computation is finished you can look for NaNs to check whether something went wrong.
浮点运算的目的是产生(相对)快速的计算来保存错误。在漫长的计算过程中,你不会检查溢流或其他废话;你要等到它完成。这就是为什么NaNs会像他们一样传播:一旦你得到了一个NaN,你能做的事情很少会让它消失。一旦计算完成,您可以寻找NaNs来检查是否发生了错误。
Same for infinities: if there's a possibility of overflow, don't do things that will throw away infinities.
不定式也一样:如果有可能发生溢出,不要做会把不定式扔掉的事情。
If you want to go slow and safe, IEEE-754 has mechanisms for installing trap handlers to provide callbacks into your code when the result of a calculation would be a NaN or an infinity. Mostly that's not used; it's usually too slow, and pointless once the code has been properly debugged (not that that's easy: people get PhD's in how to do this stuff well).
如果您希望运行缓慢且安全,IEEE-754具有安装trap处理程序的机制,以便在计算结果为NaN或无穷大时向代码提供回调。主要是不习惯;它通常太慢,而且一旦代码被正确地调试出来就毫无意义了(这并不容易:人们获得了如何把这些东西做好的博士学位)。
#4
4
Another perspective that justifies "infinite" values being equal is to avoid cardinality concept altogether. Essentially if you cannot speculate on "just how infinite a value is compared to another, given that both are infinite" it's simpler to assume that Inf = Inf
.
证明“无限”值相等的另一个观点是完全避免基数概念。本质上,如果你不能推测“一个值与另一个值的无限大,假设两者都是无限大的”,那么就更容易假设Inf = Inf。
Edit: as clarification on my comment regarding cardinality I'll give two examples regarding comparison (or equality) of infinite quantities.
编辑:作为对我关于基数的评论的澄清,我将给出两个关于无穷大的比较(或相等)的例子。
Consider the set of positive integers S1 = {1,2,3, ...}
, which is infinite. Also consider the set of even integers S2 = {2,4,6, ...}
, which are also infinite. While there are clearly twice as many elements in S1 as in S2, they have "equally many" elements since you can easily have a one-to-one function between the sets, i.e. 1 -> 2
, 2-> 4
, ... They have thus the same cardinality.
考虑正整数的集合S1 ={1,2,3,…}是无穷大。还要考虑偶数的集合S2 ={2,4,6,…},也是无限的。虽然S1中元素的数量明显是S2中的两倍,但它们的元素“同样多”,因为在集合之间很容易有一个一对一的函数,即1 - >2,2 -> 4,……因此它们具有相同的基数。
Consider instead the set of real numbers R
, and the set of integers I
. Again both are infinite sets. However for each integer i
there are infinitely many real numbers between (i, i+1)
. Thus no one-to-one function can map the elements of these two sets, and thus their cardinality is different.
考虑实数R的集合和整数i的集合。同样,它们都是无限集。但是对于每个整数i,在(i, i+1)之间有无穷多个实数。因此,没有一个一对一的函数可以映射这两个集合的元素,因此它们的基数是不同的。
Bottomline: equality of infinite quantities is complicated, easier to avoid it in imperative languages :)
底线:无限数量的平等是复杂的,更容易避免在命令式语言中:)
#5
3
To me, it seems that "because it should behave the same as zero" would make a good answer. Arithmetic overflow and underflow should be handlable similarly.
在我看来,“因为它的行为应该与零相同”是一个很好的答案。算术溢出和欠流同样可以处理。
If you underflow from the largest near-infinitesimally small value which can be stored in a float, you get zero, and zeros compare as identical.
如果你从最大的接近无穷小的值下流动可以存储在一个浮点数中,你会得到0,而0和0是相同的。
If you overflow from the largest near-infinitely large value which can be stored in a float, you get INF, and INFs compare as identical.
如果从可以存储在浮动中的最大的接近无限大的值溢出,就会得到INF,并将INFs作为相同的值进行比较。
This means that code which handles numbers which are out-of-scope in both directions will not require separate special-casing for one or the other. Instead, either both or neither will need to be treated differently.
这意味着处理两个方向上超出范围的数字的代码不需要为其中一个或另一个单独的特殊框。相反,两者或两者都需要区别对待。
And the simplest requirement is covered by the "neither" case: you want to check if something over/underflowed, you can compare it to zero/INF using just the normal arithmetic comparison operators, without needing to know you current language's special syntax for the checking command: is it Math.isInfinite(), Float.checkForPositiveInfinity(), hasOverflowed()...?
最简单的要求被“两种情况”所覆盖:您要检查是否有溢出/溢出,您可以使用普通算术比较运算符将其与0 /INF进行比较,而不需要知道您当前语言的检查命令的特殊语法:是Math.isInfinite()、Float.checkForPositiveInfinity()、hasoverflow()…?
#6
2
The correct answer is a simple "because the standard (and the docs) say so". But I'm not gonna be cynical because it's obvious that's not what you are after.
正确的答案很简单,“因为标准(和文档)是这么说的”。但我不会愤世嫉俗因为这显然不是你想要的。
In addition to the other answers here, I'll try to relate the infinities to saturating arithmetic.
除了这里的其他答案,我将尝试把不定式和饱和算法联系起来。
Other answers have already stated that the reason the comparisons on NaNs result in true
, so I'm not gonna beat a dead horse.
其他的答案已经说明了在NaNs上的比较结果是正确的,所以我不会白费力气。
Let's say I have a saturating integer that represents grayscale colors. Why am I using saturating arithmetic? Because anything brighter than white is still white, and anything darker than black is still black (except orange). That means BLACK - x == BLACK
and WHITE + x == WHITE
. Makes sense?
假设我有一个表示灰度颜色的饱和整数。为什么我要使用饱和算法?因为任何比白色亮的都是白色,比黑色暗的都是黑色(除了橙色)。这意味着黑- x ==黑和白+ x ==白。有道理吗?
Now, let's say we want to represent those grayscale colors with a (signed) 1s complement 8-bit integer where BLACK == -127
and WHITE == 127
. Why 1s complement? Because it gives us a signed zero like IEEE 754 floating point. And, because we are using saturating arithmetic, -127 - x == -127
and 127 + x == 127
.
现在,假设我们要用一个(有符号的)1s补8位整数来表示这些灰度颜色,其中黑色= -127,白色= 127。为什么1 s补?因为它给我们一个有符号的0,像IEEE 754浮点数。而且,因为我们使用的是饱和算术,-127 - x = -127和127 + x == 127。
How does this relate to floating point infinities? Replace the integer with floating point, BLACK
with NEGATIVE_INFINITY
, and WHITE
with POSITIVE_INFINITY
and what do you get? NEGATIVE_INFINITY - x == NEGATIVE_INFINITY
and POSITIVE_INFINITY + x == POSITIVE_INFINITY
.
这如何与浮点数的无穷大有关呢?将整数替换为浮点数,黑色替换为负无穷,白色替换为正无穷,得到什么?负无穷- x =负无穷+ x =正无穷。
Since you used POSITIVE_INFINITY
, I'll use it also. First we need a class to represent our saturating integer-based color; let's call it SaturatedColor
and assume it works like any other integer in Java. Now, let's take your code and replace double
with our own SaturatedColor
and Double.POSITIVE_INFINITY
with SaturatedColor.WHITE
:
既然你用了POSITIVE_INFINITY,我也用它。首先,我们需要一个类来表示饱和的基于整数的颜色;我们称它为饱和度颜色,并假设它与Java中的任何其他整数一样工作。现在,让我们使用您的代码,用我们自己的饱和颜色替换double。POSITIVE_INFINITY SaturatedColor.WHITE:
SaturatedColor a = SaturatedColor.WHITE;
SaturatedColor b = SaturatedColor.WHITE;
As we established above, SaturatedColor.WHITE
(just WHITE
above) is 127
, so let's do that here:
如上所述,饱和色。白色(上面是白色)是127,我们在这里做一下:
SaturatedColor a = 127;
SaturatedColor b = 127;
Now we take the System.out.println
statements you used and replace a
and b
with their value (values?):
现在我们把系统拿出来。使用println语句并将a和b替换为它们的值(值?):
System.out.println(127 == 127);
System.out.println(127 < 127);
System.out.println(127 > 127);
It should be obvious what this will print.
很明显,它将印刷什么。
#7
2
Since Double.Nan.equals (Double.NaN) was mentioned: It's one thing what should happen when you perform arithmetic and compare numbers, it's a totally different thing when you consider how objects should behave.
因为Double.Nan。= (Double.NaN)提到:当你执行算术和比较数字时,应该发生的事情是,当你考虑对象的行为时,这是完全不同的事情。
Two typical problem cases are: Sorting an array of numbers, and using hash values to implement dictionaries, sets, and so on. There are two exceptional cases where the normal ordering with <, = and > doesn't apply: One case is that +0 = -0 and the other is that NaN ≠ NaN, and x < NaN, x > NaN, x = NaN will always be false whatever x is.
两个典型的问题案例是:对数字数组进行排序,以及使用哈希值实现字典、集等等。有两个特殊情况下正常订购< =,>,不适用:一种情况是,+ 0 = 0,另一个是南≠南,和x <南x> 南,x =南总是会错误无论x。
Sorting algorithms can get into trouble with this. A sorting algorithm may assume that x = x is always true. So if I know that x is stored in an array and look for it, I might not do any bounds check because the search for it must find something. Not if x is NaN. A sorting algorithm may assume that exactly one of a < b and a >= b must be true. Not if one is NaN. So a naive sorting algorithm may crash when NaNs are present. You'd have to decide where you want NaNs to end up when sorting the array, and then change your comparison code so that it works.
排序算法可能会遇到麻烦。排序算法可能假设x = x总是正确的。如果我知道x被存储在数组中并查找它,我可能不会做任何边界检查因为搜索它必须找到一些东西。不是如果x是NaN。排序算法可以假设A < b和>= b必须为真。如果一个人是南,那就不是。因此,当存在NaNs时,一种朴素的排序算法可能会崩溃。在排序数组时,您必须决定希望NaNs在哪里结束,然后更改比较代码以使其工作。
Now dictionaries and sets and generally hashing: What if I use an NaN as the key? A set contains unique objects. If the set contains an NaN and I try to add another one, is it unique because it is not equal to the one that is already there? What about +0 and -0, should they be considered equal or different? There's the rule that any two items considered equal must have the same hash value. So the sensible thing is (probably) that a hash function returns one unique value for all NaNs, and one unique value for +0 and -0. And after the hash lookup when you need to find an element with the same hash value that is actually equal, two NaNs should be considered equal (but different from anything else).
现在,字典和集合以及一般的散列:如果我使用NaN作为键呢?集合包含唯一的对象。如果集合包含一个NaN,我尝试添加另一个,它是唯一的吗,因为它不等于已经存在的那个?那么+0和-0呢,它们是相等的还是不同的呢?有一个规则,任何两个被认为相等的项必须具有相同的哈希值。因此,(很可能)一个哈希函数返回一个唯一的值给所有的NaNs,一个唯一的值给+0和-0。在哈希查找之后,当您需要找到一个具有相同哈希值的元素时,应该认为两个NaNs是相等的(但与其他任何东西不同)。
That's probably why Double.Nan.equal () behaves different from ==.
这可能是为什么Double.Nan。等号()的行为与=不同。
#8
1
This is because NaN is not a number and is therefore not equal to any number including NaN.
这是因为NaN不是一个数字,因此不等于任何数字,包括NaN。
#1
70
Your reasoning is that Double.POSITIVE_INFINITY
should not be equal to itself because it is “likely” to have been obtained as the result of a loss of accuracy.
你的推理是双重的。POSITIVE_INFINITY不应该等于它本身,因为它“可能”是由于失去了准确性而获得的。
This line of reasoning applies to all of floating-point. Any finite value can be obtained as the result of an inaccurate operation. That did not push the IEEE 754 standardization committee to define ==
as always evaluating to false for finite values, so why should infinities be different?
这种推理方法适用于所有浮点数。由于操作不准确,可以得到任何有限值。这并没有促使IEEE 754标准化委员会定义== =,因为对于有限的值,总是将其评估为false,那么为什么不定式应该是不同的呢?
As defined, ==
is useful for people who understand what it does (that is, test the floating-point values that have been obtained, and certainly not the values that should have been obtained with real computations). For anyone who understands that, and you need to understand it to use floating-point even for computations that do not involve infinity, having Double.POSITIVE_INFINITY == Double.POSITIVE_INFINITY
evaluate to true is convenient, if only to test if the floating-point result of a floating-point computation is Double.POSITIVE_INFINITY
.
如定义的那样,==对于理解它的功能的人是有用的(也就是说,测试已经获得的浮点值,而不是真正的计算应该获得的值)。对于任何理解这一点的人,你需要理解它使用浮点数,即使计算不涉及无穷,有两倍。POSITIVE_INFINITY = =翻倍。POSITIVE_INFINITY评估为true是很方便的,如果只是为了测试浮点计算的浮点结果是否为Double.POSITIVE_INFINITY。
That leaves the question of why NaN can afford to have special behavior, and infinities should follow the same general principles as finite values. NaN is different from infinities: the underlying principle of the IEEE 754 standard is that values are exactly what they are, but the result of an operation can be approximated with respect to the real result, and in this case, the resulting floating-point value is obtained according to the rounding mode.
这就留下了一个问题:为什么NaN能够承担得起特殊的行为,不定式应该遵循与有限值相同的一般原则。南不同于无穷大:IEEE 754标准的基本原则是,值是什么,但一个操作的结果可以近似对真正的结果,在这种情况下,产生的浮点值是根据获得的舍入模式。
Forget for an instant that 1.0 / 0.0
is defined as +inf, which is an annoyance in this discussion. Think for the moment of Double.POSITIVE_INFINITY
only as the result of operations such as 1.0e100 / 1.0e-300
or Double.MAX_VALUE + Double.MAX_VALUE
. For these operations, +inf is the closest approximation of the real result, just like for operations that produce a finite result. By contrast, NaN is the result you obtain when the operation doesn't make sense. It is defensible to have NaN behave specially, but inf is just an approximation of all the values too large to represent.
暂时忘记1.0 / 0.0被定义为+inf,这在本讨论中很烦人。想一下双重的时刻。只能进行1。0e100 / 1。0e-300或2。MAX_VALUE + Double.MAX_VALUE。对于这些操作,+inf是真实结果的最接近近似值,就像产生有限结果的操作一样。相反,NaN是当操作没有意义时得到的结果。让NaN有特殊行为是有道理的,但是inf只是所有值的近似值,这些值太大而无法表示。
In reality, 1.0 / 0.0
also produces +inf, but that should be considered an exception. It would have been just as coherent to define the result of that operation as NaN, but defining it as +inf was more convenient in the implementation of some algorithms. An example is provided page 10 in Kahan's notes. More details than most will wish for are in the article “Branch Cuts for Complex Elementary Functions, or Much Ado About Nothing's Sign Bit”. I would also interpret the existence in IEEE 754 of a “division by zero” flag separate from the NaN flag as recognition that the user may want to treat division by zero specially although it is not defined as producing NaN.
实际上,1.0 / 0.0也生成+inf,但这应该被视为一个例外。将该操作的结果定义为NaN应该和nf一样一致,但是将其定义为+inf在实现某些算法时更方便。在Kahan的笔记中提供了一个例子。比大多数人所希望的更详细的是在“复杂基本函数的分支削减,或关于无符号比特的麻烦”这篇文章中。我还将IEEE 754中“零除”标志与NaN标志分离的存在解释为用户可能希望通过0来处理除法,尽管它没有定义为生成NaN。
#2
6
Because thats the standard. Infinity represents a number greater than or less than Double.MAX_VALUE/-Double.MAX_VALUE.
因为这是标准的。无穷大表示大于或小于doubley . max_value /- doubley . max_value。
NaN represents the outcome of an operation that didn't make sense. That is, the operation didn't possibly come out with a number.
NaN代表了一个没有意义的操作的结果。也就是说,手术不可能得到一个数字。
I would guess the logic is once a number gets big enough (infinity) and because of the limitation of floating point numbers, adding numbers to it won't change the outcome, so its 'like' infinity.
我猜逻辑是,当一个数字变得足够大(无穷大)并且由于浮点数的限制,加上数字不会改变结果,所以它是“无穷大”。
So if you want to compare to really big numbers, at some point you might just say those two big numbers are close enough for all intents and purposes. But if you want to compare two things that both aren't numbers, you can't compare them so its false. At least you couldn't compare them as a primitive.
所以如果你想和真正的大数相比,在某种程度上你可能会说这两个大数足够接近于所有的意图和目的。但是如果你想比较两个都不是数字的东西,你不能比较它们,所以它是假的。至少你不能把它们和原始人相比。
#3
5
Why are infinities equal? Because it works.
为什么无穷大平等?因为它的工作原理。
Floating-point arithmetic is designed to produce (relatively) fast computations that preserve errors. The idea being that you don't check for overflows or other nonsense during a lengthy calculation; you wait until it's finished. That's why NaNs propagate the way they do: once you've gotten a NaN, there are very few things you can do that will make it go away. Once the computation is finished you can look for NaNs to check whether something went wrong.
浮点运算的目的是产生(相对)快速的计算来保存错误。在漫长的计算过程中,你不会检查溢流或其他废话;你要等到它完成。这就是为什么NaNs会像他们一样传播:一旦你得到了一个NaN,你能做的事情很少会让它消失。一旦计算完成,您可以寻找NaNs来检查是否发生了错误。
Same for infinities: if there's a possibility of overflow, don't do things that will throw away infinities.
不定式也一样:如果有可能发生溢出,不要做会把不定式扔掉的事情。
If you want to go slow and safe, IEEE-754 has mechanisms for installing trap handlers to provide callbacks into your code when the result of a calculation would be a NaN or an infinity. Mostly that's not used; it's usually too slow, and pointless once the code has been properly debugged (not that that's easy: people get PhD's in how to do this stuff well).
如果您希望运行缓慢且安全,IEEE-754具有安装trap处理程序的机制,以便在计算结果为NaN或无穷大时向代码提供回调。主要是不习惯;它通常太慢,而且一旦代码被正确地调试出来就毫无意义了(这并不容易:人们获得了如何把这些东西做好的博士学位)。
#4
4
Another perspective that justifies "infinite" values being equal is to avoid cardinality concept altogether. Essentially if you cannot speculate on "just how infinite a value is compared to another, given that both are infinite" it's simpler to assume that Inf = Inf
.
证明“无限”值相等的另一个观点是完全避免基数概念。本质上,如果你不能推测“一个值与另一个值的无限大,假设两者都是无限大的”,那么就更容易假设Inf = Inf。
Edit: as clarification on my comment regarding cardinality I'll give two examples regarding comparison (or equality) of infinite quantities.
编辑:作为对我关于基数的评论的澄清,我将给出两个关于无穷大的比较(或相等)的例子。
Consider the set of positive integers S1 = {1,2,3, ...}
, which is infinite. Also consider the set of even integers S2 = {2,4,6, ...}
, which are also infinite. While there are clearly twice as many elements in S1 as in S2, they have "equally many" elements since you can easily have a one-to-one function between the sets, i.e. 1 -> 2
, 2-> 4
, ... They have thus the same cardinality.
考虑正整数的集合S1 ={1,2,3,…}是无穷大。还要考虑偶数的集合S2 ={2,4,6,…},也是无限的。虽然S1中元素的数量明显是S2中的两倍,但它们的元素“同样多”,因为在集合之间很容易有一个一对一的函数,即1 - >2,2 -> 4,……因此它们具有相同的基数。
Consider instead the set of real numbers R
, and the set of integers I
. Again both are infinite sets. However for each integer i
there are infinitely many real numbers between (i, i+1)
. Thus no one-to-one function can map the elements of these two sets, and thus their cardinality is different.
考虑实数R的集合和整数i的集合。同样,它们都是无限集。但是对于每个整数i,在(i, i+1)之间有无穷多个实数。因此,没有一个一对一的函数可以映射这两个集合的元素,因此它们的基数是不同的。
Bottomline: equality of infinite quantities is complicated, easier to avoid it in imperative languages :)
底线:无限数量的平等是复杂的,更容易避免在命令式语言中:)
#5
3
To me, it seems that "because it should behave the same as zero" would make a good answer. Arithmetic overflow and underflow should be handlable similarly.
在我看来,“因为它的行为应该与零相同”是一个很好的答案。算术溢出和欠流同样可以处理。
If you underflow from the largest near-infinitesimally small value which can be stored in a float, you get zero, and zeros compare as identical.
如果你从最大的接近无穷小的值下流动可以存储在一个浮点数中,你会得到0,而0和0是相同的。
If you overflow from the largest near-infinitely large value which can be stored in a float, you get INF, and INFs compare as identical.
如果从可以存储在浮动中的最大的接近无限大的值溢出,就会得到INF,并将INFs作为相同的值进行比较。
This means that code which handles numbers which are out-of-scope in both directions will not require separate special-casing for one or the other. Instead, either both or neither will need to be treated differently.
这意味着处理两个方向上超出范围的数字的代码不需要为其中一个或另一个单独的特殊框。相反,两者或两者都需要区别对待。
And the simplest requirement is covered by the "neither" case: you want to check if something over/underflowed, you can compare it to zero/INF using just the normal arithmetic comparison operators, without needing to know you current language's special syntax for the checking command: is it Math.isInfinite(), Float.checkForPositiveInfinity(), hasOverflowed()...?
最简单的要求被“两种情况”所覆盖:您要检查是否有溢出/溢出,您可以使用普通算术比较运算符将其与0 /INF进行比较,而不需要知道您当前语言的检查命令的特殊语法:是Math.isInfinite()、Float.checkForPositiveInfinity()、hasoverflow()…?
#6
2
The correct answer is a simple "because the standard (and the docs) say so". But I'm not gonna be cynical because it's obvious that's not what you are after.
正确的答案很简单,“因为标准(和文档)是这么说的”。但我不会愤世嫉俗因为这显然不是你想要的。
In addition to the other answers here, I'll try to relate the infinities to saturating arithmetic.
除了这里的其他答案,我将尝试把不定式和饱和算法联系起来。
Other answers have already stated that the reason the comparisons on NaNs result in true
, so I'm not gonna beat a dead horse.
其他的答案已经说明了在NaNs上的比较结果是正确的,所以我不会白费力气。
Let's say I have a saturating integer that represents grayscale colors. Why am I using saturating arithmetic? Because anything brighter than white is still white, and anything darker than black is still black (except orange). That means BLACK - x == BLACK
and WHITE + x == WHITE
. Makes sense?
假设我有一个表示灰度颜色的饱和整数。为什么我要使用饱和算法?因为任何比白色亮的都是白色,比黑色暗的都是黑色(除了橙色)。这意味着黑- x ==黑和白+ x ==白。有道理吗?
Now, let's say we want to represent those grayscale colors with a (signed) 1s complement 8-bit integer where BLACK == -127
and WHITE == 127
. Why 1s complement? Because it gives us a signed zero like IEEE 754 floating point. And, because we are using saturating arithmetic, -127 - x == -127
and 127 + x == 127
.
现在,假设我们要用一个(有符号的)1s补8位整数来表示这些灰度颜色,其中黑色= -127,白色= 127。为什么1 s补?因为它给我们一个有符号的0,像IEEE 754浮点数。而且,因为我们使用的是饱和算术,-127 - x = -127和127 + x == 127。
How does this relate to floating point infinities? Replace the integer with floating point, BLACK
with NEGATIVE_INFINITY
, and WHITE
with POSITIVE_INFINITY
and what do you get? NEGATIVE_INFINITY - x == NEGATIVE_INFINITY
and POSITIVE_INFINITY + x == POSITIVE_INFINITY
.
这如何与浮点数的无穷大有关呢?将整数替换为浮点数,黑色替换为负无穷,白色替换为正无穷,得到什么?负无穷- x =负无穷+ x =正无穷。
Since you used POSITIVE_INFINITY
, I'll use it also. First we need a class to represent our saturating integer-based color; let's call it SaturatedColor
and assume it works like any other integer in Java. Now, let's take your code and replace double
with our own SaturatedColor
and Double.POSITIVE_INFINITY
with SaturatedColor.WHITE
:
既然你用了POSITIVE_INFINITY,我也用它。首先,我们需要一个类来表示饱和的基于整数的颜色;我们称它为饱和度颜色,并假设它与Java中的任何其他整数一样工作。现在,让我们使用您的代码,用我们自己的饱和颜色替换double。POSITIVE_INFINITY SaturatedColor.WHITE:
SaturatedColor a = SaturatedColor.WHITE;
SaturatedColor b = SaturatedColor.WHITE;
As we established above, SaturatedColor.WHITE
(just WHITE
above) is 127
, so let's do that here:
如上所述,饱和色。白色(上面是白色)是127,我们在这里做一下:
SaturatedColor a = 127;
SaturatedColor b = 127;
Now we take the System.out.println
statements you used and replace a
and b
with their value (values?):
现在我们把系统拿出来。使用println语句并将a和b替换为它们的值(值?):
System.out.println(127 == 127);
System.out.println(127 < 127);
System.out.println(127 > 127);
It should be obvious what this will print.
很明显,它将印刷什么。
#7
2
Since Double.Nan.equals (Double.NaN) was mentioned: It's one thing what should happen when you perform arithmetic and compare numbers, it's a totally different thing when you consider how objects should behave.
因为Double.Nan。= (Double.NaN)提到:当你执行算术和比较数字时,应该发生的事情是,当你考虑对象的行为时,这是完全不同的事情。
Two typical problem cases are: Sorting an array of numbers, and using hash values to implement dictionaries, sets, and so on. There are two exceptional cases where the normal ordering with <, = and > doesn't apply: One case is that +0 = -0 and the other is that NaN ≠ NaN, and x < NaN, x > NaN, x = NaN will always be false whatever x is.
两个典型的问题案例是:对数字数组进行排序,以及使用哈希值实现字典、集等等。有两个特殊情况下正常订购< =,>,不适用:一种情况是,+ 0 = 0,另一个是南≠南,和x <南x> 南,x =南总是会错误无论x。
Sorting algorithms can get into trouble with this. A sorting algorithm may assume that x = x is always true. So if I know that x is stored in an array and look for it, I might not do any bounds check because the search for it must find something. Not if x is NaN. A sorting algorithm may assume that exactly one of a < b and a >= b must be true. Not if one is NaN. So a naive sorting algorithm may crash when NaNs are present. You'd have to decide where you want NaNs to end up when sorting the array, and then change your comparison code so that it works.
排序算法可能会遇到麻烦。排序算法可能假设x = x总是正确的。如果我知道x被存储在数组中并查找它,我可能不会做任何边界检查因为搜索它必须找到一些东西。不是如果x是NaN。排序算法可以假设A < b和>= b必须为真。如果一个人是南,那就不是。因此,当存在NaNs时,一种朴素的排序算法可能会崩溃。在排序数组时,您必须决定希望NaNs在哪里结束,然后更改比较代码以使其工作。
Now dictionaries and sets and generally hashing: What if I use an NaN as the key? A set contains unique objects. If the set contains an NaN and I try to add another one, is it unique because it is not equal to the one that is already there? What about +0 and -0, should they be considered equal or different? There's the rule that any two items considered equal must have the same hash value. So the sensible thing is (probably) that a hash function returns one unique value for all NaNs, and one unique value for +0 and -0. And after the hash lookup when you need to find an element with the same hash value that is actually equal, two NaNs should be considered equal (but different from anything else).
现在,字典和集合以及一般的散列:如果我使用NaN作为键呢?集合包含唯一的对象。如果集合包含一个NaN,我尝试添加另一个,它是唯一的吗,因为它不等于已经存在的那个?那么+0和-0呢,它们是相等的还是不同的呢?有一个规则,任何两个被认为相等的项必须具有相同的哈希值。因此,(很可能)一个哈希函数返回一个唯一的值给所有的NaNs,一个唯一的值给+0和-0。在哈希查找之后,当您需要找到一个具有相同哈希值的元素时,应该认为两个NaNs是相等的(但与其他任何东西不同)。
That's probably why Double.Nan.equal () behaves different from ==.
这可能是为什么Double.Nan。等号()的行为与=不同。
#8
1
This is because NaN is not a number and is therefore not equal to any number including NaN.
这是因为NaN不是一个数字,因此不等于任何数字,包括NaN。