從干將莫邪的故事提及--java比較操做注意要點

故事背景html

《搜神記》:java

干將莫邪的故事--java比較操做注意要點

 

楚干將、莫邪爲楚王做劍,三年乃成。王怒,欲殺之。劍有雌雄。其妻重身當產。夫語妻曰:「吾爲王做劍,三年乃成。王怒,往必殺我。汝若生子是男,大,告之曰:‘出戶望南山,鬆生石上,劍在其背。’」因而即將雌劍往見楚王。王大怒,使相之:「劍有二,一雄一雌,雌來雄不來。」王怒,即殺之。oracle

莫邪子名赤,比後壯,乃問其母曰:「吾父所在?」母曰:「汝父爲楚王做劍,三年乃成。王怒殺之。去時囑我:‘語汝子,出戶望南山,鬆生石上,劍在其背。’」因而子出戶南望,不見有山,但睹(dû)堂前鬆柱下石低之上。即以斧破其背,得劍,日夜思欲報楚王。less

王夢見一兒,眉間廣尺,言欲報仇。王即購之千金。兒聞之,亡去,入山行歌。客有逢者,謂:「子年少,何哭之甚悲耶(yé)?」曰:「吾干將、莫邪子也,楚王殺吾父,吾欲報之!」客曰:「聞王購子頭千金,將子頭與劍來,爲子報之。」兒曰:「幸甚!」即自刎(wên),兩手捧頭及劍奉之,立僵。客曰:「不負子也。」因而屍乃僕。ide

客持頭往見楚王,王大喜。客曰:「此乃勇士頭也,當於湯鑊(huò)煮之。」王如其言。煮頭三日三夕,不爛,頭踔出湯中,瞋目大怒。客曰:「此兒頭不爛,願王自往臨視之,是必爛也。」王即臨之。客以劍擬王,王頭隨墜湯中,客亦自擬己頭,頭復墜湯中。三首俱爛,不可識辨。乃分其湯肉葬之,故通名「三王墓」,今在汝南北宜春縣界。測試

java中的雌雄雙劍0與-0spa

干將莫邪的故事--java比較操做注意要點

 

0與-0按理說都是同樣的,但在程序中不必定就相等哦。請看下面的程序:code

    public static void main(String[] args) {
        System.out.println(Float.compare(-0.0f, 0.0f));
        System.out.println(Math.max(-0.0f, 0.0f));
        System.out.println(Math.min(-0.0f, 0.0));
        System.out.println(-0.0f<0.0f);
        System.out.println(-0.0f<=0.0f);
    }

上面的結果可能讓你大吃一驚。orm

-1
0.0
-0.0
false
true

讓咱們看看JSL上怎麼說吧htm

15.20.1. Numerical Comparison Operators <, <=, >, and >=
The type of each of the operands of a numerical comparison operator must be a type that is convertible (§5.1.8) to a primitive numeric type, or a compile-time error occurs.
Binary numeric promotion is performed on the operands (§5.6.2).
Note that binary numeric promotion performs value set conversion (§5.1.13) and may perform unboxing conversion (§5.1.8).
If the promoted type of the operands is int or long, then signed integer comparison is performed.
If the promoted type is float or double, then floating-point comparison is performed.
Comparison is carried out accurately on floating-point values, no matter what value sets their representing values were drawn from.
The result of a floating-point comparison, as determined by the specification of the IEEE 754 standard, is:
If either operand is NaN, then the result is false.
All values other than NaN are ordered, with negative infinity less than all finite values, and positive infinity greater than all finite values.
Positive zero and negative zero are considered equal.
For example, -0.0<0.0 is false, but -0.0<=0.0 is true.
Note, however, that the methods Math.min and Math.max treat negative zero as being strictly smaller than positive zero.
Subject to these considerations for floating-point numbers, the following rules then hold for integer operands or for floating-point operands other than NaN:
The value produced by the < operator is true if the value of the left-hand operand is less than the value of the right-hand operand, and otherwise is false.
The value produced by the <= operator is true if the value of the left-hand operand is less than or equal to the value of the right-hand operand, and otherwise is false.
The value produced by the > operator is true if the value of the left-hand operand is greater than the value of the right-hand operand, and otherwise is false.
The value produced by the >= operator is true if the value of the left-hand operand is greater than or equal to the value of the right-hand operand, and otherwise is false.
干將莫邪的故事--java比較操做注意要點

 

Positive zero and negative zero are considered equal.(浮點數中0.0和-0.0進行關係比較是相等的)

For example, -0.0<0.0 is false, but -0.0<=0.0 is true.(例如:-0.0<0.0是false,但-0.0<=0.0 是true)

Note, however, that the methods Math.min and Math.max treat negative zero as being strictly smaller than positive zero.(主意:然而,使用Math.min和Math.max進行浮點數比較時,-0.0時小於0.0的)

java中浮點數在循環中使用要慎重

    public static void main(String[] args) {
        final int START = 2000000000;
        int count = 0;
        for (float f = START; f < START + 50; f++)
        count++;
        System.out.println(count);
        }

f的初始值接近於Integer.MAX_VALUE,所以它須要用31 位來精確表示,而float 類型只能提供24 位的精度。對如此巨大的一個float 數值進行增量操做將不會改變其值。所以,這個程序看起來應該無限地循環下去,由於f 永遠也不可能解決其終止值。可是,若是你運行該程序,就會發現它並無無限循環下去,事實上,它當即就終止了,並打印出0。怎麼回事呢?

問題在於終止條件測試失敗了,其方式與增量操做失敗的方式很是類似。這個循環只有在循環索引f 比(float)(START + 50)小的狀況下才運行。在將一個int與一個float 進行比較時,會自動執行從int 到float 的提高[JLS 15.20.1]。遺憾的是,這種提高是會致使精度丟失的三種拓寬原始類型轉換的一種[JLS5.1.2]。(另外兩個是從long 到float 和從long 到double。)

f 的初始值太大了,以致於在對其加上50,而後將結果轉型爲float 時,所產生的數值等於直接將f 轉換成float 的數值。換句話說,(float)2000000000 ==2000000050,所以表達式f < START + 50 即便是在循環體第一次執行以前就是false,因此,循環體也就永遠的不到機會去運行。

總結

數據比較的時候,儘可能避開浮點數,使用int,long等。

參考資料

【1】https://baike.baidu.com/item/%E5%B9%B2%E5%B0%86%E8%8E%AB%E9%82%AA/550371?fr=aladdin

【2】https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.20.1

相關文章
相關標籤/搜索