簡體   English   中英

混合浮點運算和長時間計算會產生錯誤的答案,沒有編譯器警告

[英]Mixed float and long calculation yields wrong answer with no compiler warning

以下代碼為startTime輸出錯誤的值是否令人驚訝?

public class Temp {
    public static void main(String args[]){
       float duration = (float) 2.0;
       long endTime = 1353728995;
       long startTime = 0;
       startTime = (long) (endTime - duration);
       System.out.println(startTime);
}
}

它不會輸出錯誤的值。 它只會輸出您不期望的值。

重要的一點是這里發生了什么:

endTime - duration

實際評估為:

(float) endTime - duration;

那就是數據丟失的地方。 最接近1353728995的float值是1353729024,最接近2的結果的最接近float 仍然是 1353729024。

這些都遵循語言規范。 JLS第15.8.2節 (加法運算符)指出,二進制數值提升適用於操作數。

第5.6.2節(二進制數字提升)像這樣開始:

當運算符將二進制數字提升應用於一對操作數時,每個操作數必須表示一個可轉換為數字類型的值,以下規則適用:

  • 如果任何操作數是引用類型,則將其進行拆箱轉換(第5.1.8節)。

  • 擴展原語轉換(第5.1.2節)適用於轉換以下規則指定的一個或兩個操作數:

    • 如果一個操作數的類型為double,則另一個將轉換為double。

    • 否則,如果其中一個操作數的類型為float ,則另一個將轉換為float

    • ...

因此,遵循這些規則,將endTimelong值轉換為float ,然后在float算法中執行減法。

請記住, float只能提供7個有效數字,我希望其余的數字非常明顯。

請注意,如果不將結果強制轉換為long ,則編譯器將更清楚地說明發生了什么:

Test.java:8: error: possible loss of precision
    long startTime = endTime - duration;
                             ^
  required: long
  found:    float
1 error

這非常清楚地表明結果將是float ,這應該引起警告,說明將如何執行操作以及可以預期的精度。

如果需要,可以將浮點數轉換為long。

 float duration = (float) 2.0;
    long endTime = 1353728995;
    long startTime = 0;
    startTime = endTime - (long)duration;
    System.out.println(startTime);

輸出:

1353728993

如果不進行強制轉換,則將其視為浮點值,並且結果將是意外的。

這都是因為浮點符號。

當使用float作為至少一個參數執行任何操作時,所有參與的數字都會提升為float 在這里,您的endTime將在減法之前轉換為浮點數1.35372902E9 ,因為它使用了指數表示IEEE 754 notationIEEE 754 notation 這種表示方式不是很精確,因此您會看到不同的結果。

好像在做

    startTime =  (endTime - (long)duration);

然后使用它的時間很長,您應該會得到預期的結果。

doublefloat經常會降低精度。 您在這里看到的可能是哪種。

請注意,您實際上正在計算:

startTime = (long) ((float)endTime - duration);

因為編譯器會自動將long轉換為float以進行減法。 這是有據可查的,並且一些出色的代碼檢查器實際上會警告您。

您可能想要的是:

startTime = endTime - (long)duration;

但是那你應該這樣說。

您可能還可以通過使用獲得正確的

startTime = (long) (endTime - (double)duration);

但這也不安全

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM