問題描述
我正在閱讀 Joshua Bloch 的 Effective java,在 Item 8: Obey the general contract when overriding equals 中寫了這個(gè)語(yǔ)句
I am reading Effective java by Joshua Bloch and in Item 8: Obey the general contract when overriding equals, this statement is written
對(duì)于浮點(diǎn)字段,使用 Float.compare 方法;對(duì)于雙字段,請(qǐng)使用雙重比較.對(duì)float和double字段做了特殊處理Float.NaN、-0.0f 和類似的 double 的存在是必要的常量;
for float fields, use the Float.compare method; and for double fields, use Double.compare. The special treatment of float and double fields is made necessary by the existence of Float.NaN, -0.0f and the analogous double constants;
誰(shuí)能舉例說明為什么我們不能使用 ==
進(jìn)行浮點(diǎn)或雙重比較
Can someone explain me with example why we can't use ==
for float or double comparison
推薦答案
來(lái)自 apidoc,Float.compare
:
From apidoc, Float.compare
:
比較兩個(gè)指定的浮點(diǎn)值.返回的整數(shù)值的符號(hào)與調(diào)用將??返回的整數(shù)的符號(hào)相同:
Compares the two specified float values. The sign of the integer value returned is the same as that of the integer that would be returned by the call:
new Float(f1).compareTo(new Float(f2))
new Float(f1).compareTo(new Float(f2))
浮動(dòng).比較對(duì)象
:
比較兩個(gè) Float 對(duì)象的數(shù)值.當(dāng)應(yīng)用于原始浮點(diǎn)值時(shí),此方法執(zhí)行的比較與 Java 語(yǔ)言數(shù)值比較運(yùn)算符(<、<=、==、>= >)執(zhí)行的比較有兩種不同之處:
Compares two Float objects numerically. There are two ways in which comparisons performed by this method differ from those performed by the Java language numerical comparison operators (<, <=, ==, >= >) when applied to primitive float values:
- 此方法認(rèn)為 Float.NaN 等于其自身并且大于所有其他浮點(diǎn)值(包括 Float.POSITIVE_INFINITY).
- 此方法認(rèn)為0.0f大于-0.0f.
這確保了此方法強(qiáng)加的 Float 對(duì)象的自然順序與 equals 一致.
考慮以下代碼:
System.out.println(-0.0f == 0.0f); //true
System.out.println(Float.compare(-0.0f, 0.0f) == 0 ? true : false); //false
System.out.println(Float.NaN == Float.NaN);//false
System.out.println(Float.compare(Float.NaN, Float.NaN) == 0 ? true : false); //true
System.out.println(-0.0d == 0.0d); //true
System.out.println(Double.compare(-0.0d, 0.0d) == 0 ? true : false);//false
System.out.println(Double.NaN == Double.NaN);//false
System.out.println(Double.compare(Double.NaN, Double.NaN) == 0 ? true : false);//true
輸出不正確,因?yàn)椴皇菙?shù)字的東西,根本就不是數(shù)字,從數(shù)字比較的角度來(lái)看,應(yīng)該被視為相等.0=-0
.
The ouput is not correct, since something that is not a number, is simply not a number, and should be treated as equal from number comparison point of view. It is also clear that 0=-0
.
讓我們看看 Float.compare
會(huì):
Let's see what Float.compare
does:
public static int compare(float f1, float f2) {
if (f1 < f2)
return -1; // Neither val is NaN, thisVal is smaller
if (f1 > f2)
return 1; // Neither val is NaN, thisVal is larger
int thisBits = Float.floatToIntBits(f1);
int anotherBits = Float.floatToIntBits(f2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
Float.floatToIntBits
:
根據(jù)IEEE 754 浮點(diǎn)單一格式"位布局返回指定浮點(diǎn)值的表示形式.第 31 位(掩碼 0x80000000 選擇的位)表示浮點(diǎn)數(shù)的符號(hào).位 30-23(由掩碼 0x7f800000 選擇的位)表示指數(shù).位 22-0(由掩碼 0x007fffff 選擇的位)表示浮點(diǎn)數(shù)的有效位(有時(shí)稱為尾數(shù)).
Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "single format" bit layout. Bit 31 (the bit that is selected by the mask 0x80000000) represents the sign of the floating-point number. Bits 30-23 (the bits that are selected by the mask 0x7f800000) represent the exponent. Bits 22-0 (the bits that are selected by the mask 0x007fffff) represent the significand (sometimes called the mantissa) of the floating-point number.
如果參數(shù)為正無(wú)窮大,則結(jié)果為 0x7f800000.
If the argument is positive infinity, the result is 0x7f800000.
如果參數(shù)為負(fù)無(wú)窮大,則結(jié)果為 0xff800000.
If the argument is negative infinity, the result is 0xff800000.
如果參數(shù)為 NaN,則結(jié)果為 0x7fc00000.
If the argument is NaN, the result is 0x7fc00000.
在所有情況下,結(jié)果都是一個(gè)整數(shù),當(dāng)將它提供給 intBitsToFloat(int) 方法時(shí),將產(chǎn)生一個(gè)與 floatToIntBits 的參數(shù)相同的浮點(diǎn)值(除了所有 NaN 值都折疊為單個(gè)規(guī)范"NaN 值).
In all cases, the result is an integer that, when given to the intBitsToFloat(int) method, will produce a floating-point value the same as the argument to floatToIntBits (except all NaN values are collapsed to a single "canonical" NaN value).
來(lái)自 JLS 15.20.1.數(shù)值比較運(yùn)算符 <、<=、> 和 >=
根據(jù) IEEE 754 標(biāo)準(zhǔn)的規(guī)范確定的浮點(diǎn)比較結(jié)果是:
The result of a floating-point comparison, as determined by the specification of the IEEE 754 standard, is:
如果任一操作數(shù)為 NaN,則結(jié)果為 false.
If either operand is NaN, then the result is false.
除 NaN 之外的所有值都是有序的,負(fù)無(wú)窮小于所有有限值,正無(wú)窮大于所有有限值.
All values other than NaN are ordered, with negative infinity less than all finite values, and positive infinity greater than all finite values.
正零和負(fù)零被認(rèn)為是相等的.例如,-0.0<0.0 為假,但 -0.0<=0.0 為真.
Positive zero and negative zero are considered equal. For example, -0.0<0.0 is false, but -0.0<=0.0 is true.
但請(qǐng)注意,Math.min 和 Math.max 方法將負(fù)零視為嚴(yán)格小于正零.
Note, however, that the methods Math.min and Math.max treat negative zero as being strictly smaller than positive zero.
對(duì)于操作數(shù)為正零和負(fù)零的嚴(yán)格比較,結(jié)果將是錯(cuò)誤的.
For strict comparisons where operands are positive zero and negative zero the result will be wrong.
來(lái)自 JLS 15.21.1.數(shù)值等式運(yùn)算符 == 和 !=:
根據(jù) IEEE 754 標(biāo)準(zhǔn)的規(guī)范確定的浮點(diǎn)比較結(jié)果是:
The result of a floating-point comparison, as determined by the specification of the IEEE 754 standard, is:
浮點(diǎn)相等性測(cè)試是按照 IEEE 754 標(biāo)準(zhǔn)的規(guī)則進(jìn)行的:
Floating-point equality testing is performed in accordance with the rules of the IEEE 754 standard:
如果任一操作數(shù)為 NaN,則 == 的結(jié)果為假,但 != 的結(jié)果為真.實(shí)際上,當(dāng)且僅當(dāng) x 的值為 NaN 時(shí),測(cè)試 x!=x 為真.Float.isNaN 和 Double.isNaN 方法也可以用來(lái)測(cè)試一個(gè)值是否為 NaN.
If either operand is NaN, then the result of == is false but the result of != is true. Indeed, the test x!=x is true if and only if the value of x is NaN. The methods Float.isNaN and Double.isNaN may also be used to test whether a value is NaN.
正零和負(fù)零被認(rèn)為是相等的.例如,-0.0==0.0 為真.
Positive zero and negative zero are considered equal. For example, -0.0==0.0 is true.
否則,相等運(yùn)算符會(huì)認(rèn)為兩個(gè)不同的浮點(diǎn)值不相等.特別是,有一個(gè)值表示正無(wú)窮大,一個(gè)值表示負(fù)無(wú)窮大;each 僅與自身比較相等,并且 each 與所有其他值比較不相等.
Otherwise, two distinct floating-point values are considered unequal by the equality operators. In particular, there is one value representing positive infinity and one value representing negative infinity; each compares equal only to itself, and each compares unequal to all other values.
對(duì)于兩個(gè)操作數(shù)都是 NaN 的相等比較,結(jié)果將是錯(cuò)誤的.
For equality comparisons where both operands are NaN the result will be wrong.
由于總排序(=
, <
, >
,<=
, >=
) 被許多重要的算法使用(參見 所有實(shí)現(xiàn) Comparable 接口的類) 最好使用 compare 方法,因?yàn)樗鼤?huì)產(chǎn)生更一致的行為.
Since total ordering (=
, <
, >
,<=
, >=
) is used by many important algorithms (see all the classes that implement the Comparable interface) it is better to use the compare method because it will yield more consistent behavior.
IEEE-754 標(biāo)準(zhǔn)上下文中的總排序的結(jié)果是正負(fù)零.
例如,如果您使用相等運(yùn)算符而不是比較方法,并且有一些值集合,并且您的代碼邏輯根據(jù)元素的順序做出一些決定,并且您以某種方式開始獲得多余的 NaN 值,那么它們'將被視為不同的值,而不是相同的值.
For instance, if you use the equality operator instead of the compare method, and have some collection of values and your code logic makes some decisions based on the ordering of the elements, and you somehow start getting a surplus of NaN values they'll all be treated as different values instead as the same values.
這可能會(huì)在程序的行為中產(chǎn)生與 NaN 值的數(shù)量/比率成比例的錯(cuò)誤.如果你有很多正零和負(fù)零,那只是一對(duì)會(huì)影響你的邏輯錯(cuò)誤.
That may likely produce error in the behavior of the program proportional to the amount/rate of NaN values. And if you have a lot of positive and negative zeroes, that's just one pair to affect your logic with error.
浮點(diǎn) 使用 IEEE-754 32 位格式和雙精度 使用 IEEE-754 64位格式.
Float uses IEEE-754 32 bit format and Double uses IEEE-754 64 bit format.
這篇關(guān)于為什么我們不能使用 '==' 來(lái)比較兩個(gè)浮點(diǎn)數(shù)或雙精度數(shù)的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!