問題描述
我正在閱讀 Joshua Bloch 的 Effective java,在 Item 8: Obey the general contract when overriding equals 中寫了這個語句
I am reading Effective java by Joshua Bloch and in Item 8: Obey the general contract when overriding equals, this statement is written
對于浮點字段,使用 Float.compare 方法;對于雙字段,請使用雙重比較.對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;
誰能舉例說明為什么我們不能使用 ==
進行浮點或雙重比較
Can someone explain me with example why we can't use ==
for float or double comparison
推薦答案
來自 apidoc,Float.compare
:
From apidoc, Float.compare
:
比較兩個指定的浮點值.返回的整數值的符號與調用將??返回的整數的符號相同:
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))
浮動.比較對象
:
比較兩個 Float 對象的數值.當應用于原始浮點值時,此方法執行的比較與 Java 語言數值比較運算符(<、<=、==、>= >)執行的比較有兩種不同之處:
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:
- 此方法認為 Float.NaN 等于其自身并且大于所有其他浮點值(包括 Float.POSITIVE_INFINITY).
- 此方法認為0.0f大于-0.0f.
這確保了此方法強加的 Float 對象的自然順序與 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
輸出不正確,因為不是數字的東西,根本就不是數字,從數字比較的角度來看,應該被視為相等.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
會:
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
:
根據IEEE 754 浮點單一格式"位布局返回指定浮點值的表示形式.第 31 位(掩碼 0x80000000 選擇的位)表示浮點數的符號.位 30-23(由掩碼 0x7f800000 選擇的位)表示指數.位 22-0(由掩碼 0x007fffff 選擇的位)表示浮點數的有效位(有時稱為尾數).
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.
如果參數為正無窮大,則結果為 0x7f800000.
If the argument is positive infinity, the result is 0x7f800000.
如果參數為負無窮大,則結果為 0xff800000.
If the argument is negative infinity, the result is 0xff800000.
如果參數為 NaN,則結果為 0x7fc00000.
If the argument is NaN, the result is 0x7fc00000.
在所有情況下,結果都是一個整數,當將它提供給 intBitsToFloat(int) 方法時,將產生一個與 floatToIntBits 的參數相同的浮點值(除了所有 NaN 值都折疊為單個規范"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).
來自 JLS 15.20.1.數值比較運算符 <、<=、> 和 >=
根據 IEEE 754 標準的規范確定的浮點比較結果是:
The result of a floating-point comparison, as determined by the specification of the IEEE 754 standard, is:
如果任一操作數為 NaN,則結果為 false.
If either operand is NaN, then the result is false.
除 NaN 之外的所有值都是有序的,負無窮小于所有有限值,正無窮大于所有有限值.
All values other than NaN are ordered, with negative infinity less than all finite values, and positive infinity greater than all finite values.
正零和負零被認為是相等的.例如,-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.
但請注意,Math.min 和 Math.max 方法將負零視為嚴格小于正零.
Note, however, that the methods Math.min and Math.max treat negative zero as being strictly smaller than positive zero.
對于操作數為正零和負零的嚴格比較,結果將是錯誤的.
For strict comparisons where operands are positive zero and negative zero the result will be wrong.
來自 JLS 15.21.1.數值等式運算符 == 和 !=:
根據 IEEE 754 標準的規范確定的浮點比較結果是:
The result of a floating-point comparison, as determined by the specification of the IEEE 754 standard, is:
浮點相等性測試是按照 IEEE 754 標準的規則進行的:
Floating-point equality testing is performed in accordance with the rules of the IEEE 754 standard:
如果任一操作數為 NaN,則 == 的結果為假,但 != 的結果為真.實際上,當且僅當 x 的值為 NaN 時,測試 x!=x 為真.Float.isNaN 和 Double.isNaN 方法也可以用來測試一個值是否為 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.
正零和負零被認為是相等的.例如,-0.0==0.0 為真.
Positive zero and negative zero are considered equal. For example, -0.0==0.0 is true.
否則,相等運算符會認為兩個不同的浮點值不相等.特別是,有一個值表示正無窮大,一個值表示負無窮大;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.
對于兩個操作數都是 NaN 的相等比較,結果將是錯誤的.
For equality comparisons where both operands are NaN the result will be wrong.
由于總排序(=
, <
, >
,<=
, >=
) 被許多重要的算法使用(參見 所有實現 Comparable 接口的類) 最好使用 compare 方法,因為它會產生更一致的行為.
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 標準上下文中的總排序的結果是正負零.
例如,如果您使用相等運算符而不是比較方法,并且有一些值集合,并且您的代碼邏輯根據元素的順序做出一些決定,并且您以某種方式開始獲得多余的 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.
這可能會在程序的行為中產生與 NaN 值的數量/比率成比例的錯誤.如果你有很多正零和負零,那只是一對會影響你的邏輯錯誤.
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.
浮點 使用 IEEE-754 32 位格式和雙精度 使用 IEEE-754 64位格式.
Float uses IEEE-754 32 bit format and Double uses IEEE-754 64 bit format.
這篇關于為什么我們不能使用 '==' 來比較兩個浮點數或雙精度數的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!