问题描述
我正在查看 java.lang.Math
的源代码中的某些内容,并且我注意到,当 Math.min(int,int)
(或它的长整数)对应对象)的实现方式是
I was looking through some things in the source of java.lang.Math
, and I noticed that while Math.min(int, int)
(or its long counterpart) is implemented this way:
public static int min(int a, int b) {
return a <= b ? a : b;
}
这对我来说完全有意义,与我要做的一样.但是,double/float实现是这样的:
And this makes complete sense to me and it is the same as what I would do. However, the double/float implementation is this:
public static float min(float a, float b) {
if (a != a) {
return a;
} else if (a == 0.0F && b == 0.0F && (long)Float.floatToRawIntBits(b) == negativeZeroFloatBits) {
return b;
} else {
return a <= b ? a : b;
}
}
我完全傻眼了.将 a
与自身进行比较?第二张支票还算什么?为什么它不能以与int/long版本相同的方式实现?
I'm completely dumbfounded. Comparing a
to itself? What's the second check even for? Why isn't it implemented in the same way as the int/long version?
推荐答案
浮点数字比整数值复杂得多.
Floating-point numbers are way more complicated than integer values.
对于这种特定情况,有两个区别很重要:
For this specific case two distinctions are important:
-
NaN
是float
和double
的有效值,表示不是数字".并表现怪异.即,它不等于自己. - 浮点数可以区分0.0和-0.0.当您计算某些函数的极限时,负零可能很有用.区分极限是从正方向还是负方向接近0可能是有益的.
NaN
is a valid value forfloat
anddouble
which represents "not a number" and behaves weirdly. Namely, it doesn't compare equal to itself.- Floating point numbers can differentiate between 0.0 and -0.0. A negative zero could conceivably be useful when you're calculating the limit of some function. Distinguishing whether a limit approaches 0 from the positive or the negative direction could be beneficial.
所以这部分:
if (a != a) {
return a;
}
确保如果 a
是 NaN
(如果 a
不是 NaN
,但 b
是,则稍后的"normal"检查将返回 b
,即 NaN
,因此没有显式检查这种情况下需要).这是一种常见的模式:计算任何一个输入为 NaN
的内容时,输出也将为 NaN
.由于 NaN
通常表示计算中的某些错误(例如,将值除以0),因此重要的是它会中毒".所有进一步的计算,以确保不会默默地吞下该错误.
ensures that NaN
is returned if a
is NaN
(if a
is not NaN
, but b
is, then the "normal" check later on will return b
, i.e. NaN
, so no explicit check is needed for this case). This is a common pattern: when calculating anything where one input is NaN
, the output will also be NaN
. Since NaN
usually represents some error in the calculation (such as dividing a value by 0), it's important that it "poisons" all further calculations to ensure the error isn't silently swallowed.
此部分:
if (a == 0.0F && b == 0.0F && (long)Float.floatToRawIntBits(b) == negativeZeroFloatBits) {
return b;
}
确保如果比较两个零值浮点数,并且 b
为负零,则返回负零(因为-0.0小于" 0.0).与 NaN
相似,普通检查将正确返回 a
(如果它是-0.0,而 b
是0.0).
ensures that if you compare two zero-valued floating point numbers and b
is negative zero then that negative zero is returned (since -0.0 is "smaller" than 0.0). Similarly to NaN
the normal check will correctly return a
if it's -0.0 and b
is 0.0.
这篇关于为什么Java的double/float Math.min()以这种方式实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!