2017-04-11 401 views
0

BigDecimal's constructor爲什麼Java的「新BigDecimal(double)」已被棄用?

此構造方法的結果有一定的不可預知的。一個 可能會認爲在Java中寫入new BigDecimal(0.1),創建一個 BigDecimal正好等於0.1(1未測量的值,與 比例爲1),但它實際上是等於 0.1000000000000000055511151231257827021181583404541015625。這是因爲0.1不能完全表示爲雙精度(或者對於任何有限長度的二元分數)。因此,傳遞給構造函數的值 並不完全等於 0.1,儘管如此。

String構造,在另一方面,是完全可以預測的: 寫入new BigDecimal(「0.1」)創建了一個BigDecimal正好 等於0.1,正如人們所期望。因此,一般建議 使用String構造函數而不是此 之一。

當必須使用double作爲BigDecimal的源時,請注意,此構造函數提供了精確的轉換;它不會給出與使用 Double.toString(double)方法,然後使用BigDecimal(String) 構造函數將double轉換爲字符串相同的結果 。要獲得該結果,請使用靜態valueOf(double) 方法。

那麼他們爲什麼不直接棄用它並將其功能改爲valueOf(double)?創造不可預測價值的重點是什麼?

+4

術語「不可預測」針對的是無用的程序員,並不意味着實際代碼的屬性。這種「不可預測」的陳述之後的句子使得這一點非常清楚。 – Durandal

+1

棄用問題已經解決,但不改變構造函數使用'valueOf(double)'功能的原因是Java *從不*更改已發佈API的契約。這是一件好事 - 程序應該期望它們所依賴的行爲在未來的版本中將是相同的行爲。 – VGR

+1

BigDecimal將數字保留爲字符串。如果您有一個銀行賬戶,您希望提取與您付款相同的金額。任何其他形式的記錄數字都強制從十進制轉換爲二進制系統,這意味着許多數字將具有無限小數擴展,因此必須舍入。 – Joanna

回答

5

這完全可以預測。您可以準確找到構造函數參數中提供的值。正如您所引用的,對於雙字面0.1「傳遞給構造函數的值不完全等於0.1」。構造函數忠實地提取傳入的值。可以預見。

+3

它對研究浮點行爲非常有用。 –

+1

您是否在爭論或重新解釋文檔? – shmosel

3

該程序說明new BigDecimal(double)構造函數的實際用法。其目標是顯示可以舍入給定雙精度結果的範圍。這取決於能夠獲得具有雙精度值的BigDecimal。

import java.math.BigDecimal; 

public class Test { 
    public static void main(String[] args) { 
    System.out.println(range(1.0)); 
    System.out.println(range(Math.nextUp(1.0))); 
    System.out.println(range(Math.PI)); 
    } 

    private static String range(double d){ 
    BigDecimal down = new BigDecimal(Math.nextDown(d)); 
    BigDecimal up = new BigDecimal(Math.nextUp(d)); 
    BigDecimal bd = new BigDecimal(d); 
    BigDecimal halfUp = midPoint(bd, up); 
    BigDecimal halfDown = midPoint(down, bd); 
    Boolean isEven = (Double.doubleToLongBits(d) & 1) == 0; 
    if(isEven){ 
     return "[" + halfDown + "," + halfUp + "]"; 
    } else { 
     return "(" + halfDown + "," + halfUp + ")";  
    } 
    } 

    private static BigDecimal midPoint(BigDecimal low, BigDecimal high){ 
    return low.add(high).divide(BigDecimal.valueOf(2)); 
    } 
}