2010-10-10 72 views
7

是否有東西壞了或我不明白髮生了什麼?如何通過其最小增量改變雙倍

static String getRealBinary(double val) { 
    long tmp = Double.doubleToLongBits(val); 
    StringBuilder sb = new StringBuilder(); 

    for (long n = 64; --n > 0; tmp >>= 1) 
     if ((tmp & 1) == 0) 
      sb.insert(0, ('0')); 
     else 
      sb.insert(0, ('1')); 

    sb.insert(0, '[').insert(2, "] [").insert(16, "] [").append(']'); 
    return sb.toString(); 
} 

public static void main(String[] argv) { 
    for (int j = 3; --j >= 0;) { 
     double d = j; 
     for (int i = 3; --i >= 0;) { 
      d += Double.MIN_VALUE; 
      System.out.println(d +getRealBinary(d)); 
     } 
    } 
} 

隨着輸出:

2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000] 
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000] 
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000] 
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000] 
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000] 
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000] 
4.9E-324[0] [00000000000] [000000000000000000000000000000000000000000000000001] 
1.0E-323[0] [00000000000] [000000000000000000000000000000000000000000000000010] 
1.5E-323[0] [00000000000] [000000000000000000000000000000000000000000000000011] 
+4

你想做什麼?你的問題是什麼? – Sjoerd 2010-10-10 13:19:24

+0

我的問題是:「如何通過最小的增量來改變雙倍」,這是我的努力失敗的原因。 – Margus 2010-10-10 13:21:18

+1

爲什麼不只是編輯這些位,如果你想做最小的增量,它會失敗的1和2,因爲MIN_VALUE是微小的(非常小),所以0 +真的很小=真的很小,但2+真的很小〜2 =因爲浮點值min_value與儘可能遠的點相對,而兩個點在中間的某個位置,左失去。你可以看到差異點後的大約300位數字,這意味着雙重儲存只有約15-20個有效數字。 – flownt 2010-10-10 13:23:44

回答

8

的總體思路(使用doubleToLongBits如您在getRealBinary完成),增量是長×1,並最終轉換成新長回它通過longBitsToDouble代表雙先轉換的雙重其長期表現。編輯:Java(自1.5)提供Math.ulp(double),我猜你可以用它來直接計算下一個更高的值,因此:x + Math.ulp(x)。編輯:Java(自1.5)提供Math.ulp(double),我猜你可以用它直接計算下一個更高的值:x + Math.ulp(x)

+2

從Java 1.6開始,['Math.nextAfter(start,direction)'](http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#nextAfter(double, %20double)),這更可靠。它甚至可以處理特殊情況,例如零左右。 – z0r 2015-02-19 01:08:11

7

浮點數不是均勻地分佈在數線等整數類型。當你接近無限時,它們在0附近更密集並且相距很遠。因此,您可以添加到浮點數來獲得下一個浮點數,這並不是一個常數。

+0

這怎麼可能?我們有一個尾數和一個指數。並且都不贊成0. – 2010-10-10 14:00:59

+0

@TonyEnnis:指數就是 - 指數。簡單地說,浮點數的值就像'尾數* 2 ^指數'。也就是說,改變尾數改變結果數的量完全取決於指數的值。指數越低,變化越小。 – cHao 2011-12-27 21:40:08

4

您的代碼格式不正確。您嘗試添加最小雙值並預期結果與原始值不同。問題是double.MinValue非常小,結果是四捨五入的,不會受到影響。

推薦閱讀:http://en.wikipedia.org/wiki/Machine_epsilon

在維基百科的文章有Java代碼了。 Epsilon被定義爲最小的數字,例如(X + eps * X!= X),並且eps * X被稱爲「relative-epsilon」。

0

如果您想使用BigDecimal類,則有BigDecimal.ulp()方法以及。

1

自Java 1.8以來,有java.lang.Math.nextUp(double)正在做你想要的。也有對面的java.lang.Math.nextDown(double)