簡體   English   中英

Java和浮點運算

[英]Java and floating point arithmetic

有代碼

public static final float epsilon = 0.00000001f;

public static final float a [] = {
        -180.0f,
        -180.0f + epsilon * 2,
        -epsilon * 2
}

a初始化如下:

[-180.0, -180.0, -2.0E-8]

而不是想要

[-180.0, X, Y]

如何調整epsilon以達到預期的結果? ——


1)我希望float而不是double與之前編寫的代碼保持一致
2)我不想要-179.99999998X任何其他特定數字,我想要X > -180.0X盡可能接近-180.0
3)我希望Y盡可能接近0 ,但要float
4) 我想要-180.0 < X < Y

在我最初的帖子中,我沒有具體說明我想要什么。 Patricia Shanahan 通過建議Math.ulp猜到了這Math.ulp

正如先前答案中所建議的那樣,最好的解決方案是使用double 但是,如果要使用float ,則需要考慮其在感興趣區域中的可用精度。 該程序將您的文字epsilon替換為與 180f 的最低有效位相關聯的值:

import java.util.Arrays;

public class Test {
  public static final float epsilon = Math.ulp(-180f);

  public static final float a [] = {
          -180.0f,
          -180.0f + epsilon * 2,
          -epsilon * 2
  };

  public static void main(String[] args) {
    System.out.println(Arrays.toString(a));
  }

}

輸出:

[-180.0, -179.99997, -3.0517578E-5]

盡管值0.00000001ffloat的精度范圍內,但值-180f + 0.00000001f * 2 ( -179.99999998 )不在 float只有大約 7-8 個有效位的精度,而-179.99999998至少需要 11 個。所以它的最低有效位被加法運算丟棄,不精確的值最終是-180.0f

只是為了好玩,這里是那些以位為單位的值n = -180.0f ):

sign
           | exponent       significand
           - -------- -----------------------
epsilon  = 0 01100100 01010111100110001110111
epsilon2 = 0 01100101 01010111100110001110111
n        = 1 10000110 01101000000000000000000
result   = 1 10000110 01101000000000000000000

結果最終與原始-180.0f逐位相同。

如果您使用double ,該問題就會消失,因為您沒有超過double的~15 位精度。

嘗試“雙”鍵。 如果這對您來說還不夠,請嘗試“long double”。

暫無
暫無

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

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