2014-08-27 66 views
2

一倍我有一個傳統項目,它具有使用float和長變量,像這樣的數學:更換浮子通過整個項目

long i = initWihtVeryBigNumber(); 
float multiplier = 1.3f; 
i *= multiplier; 

這主要會由於圓誤差浮動的大小,這必須被替換與:

i = (long)(i* (double)multiplier); 

或乘法器本身應該是雙重而不是浮動。

所以,如果我通過整個項目浮動更改爲雙倍的問題可能會導致任何不可預知的行爲或不?如果是的話,你能提供任何可能導致問題的例子嗎?

+2

如果您想要精確的十進制數,請改用'java.math.BigDecimal'。 – 2014-08-27 15:41:17

+0

我不確定,但有可能某些方法可能依賴浮動行爲。你應該寫一堆測試用例,進行重構,並找出答案。 – 2014-08-27 15:41:26

+0

確保你也將'1.3f'改爲'1.3d'或者只是'1.3'。如果你說'double multiplier = 1.3f',我相信它會創建一個32位的浮點數,然後將其轉換爲64位,這意味着你不會像1.3那樣接近1.3。 'float'和'double'都不會完全代表'1.3',但'float'錯誤會更大。我只是這樣說,因爲我不知道你是否打算在編輯器中做一個簡單的文本替換'float' - >'double'。 – ajb 2014-08-27 15:41:53

回答

3

所以,如果我通過整個項目浮動更改爲雙倍的問題可能會導致任何不可預知的行爲或不?如果是的話,你能提供任何可能導致問題的例子嗎?

是的。只要方法需要float,將(float)更改爲(double)可能會導致問題。例如,

Float.toString((double) 1.0f); 

是編譯錯誤。

編輯

我感興趣的運行時錯誤而不是編譯錯誤。

好的。您有第三方庫返回List<Float>(因此以下testIt()來自第三方)。如果您盲目地將該元素從List轉換爲Float,則會出現運行時錯誤。

public static List<Float> testIt() { 
    List<Float> al = new ArrayList<Float>(); 
    al.add(1.0f); 
    return al; 
} 

public static void main(String[] args) { 
    List<?> al = testIt(); 
    for (int i = 0; i < al.size(); i++) { 
     Object o = al.get(i); 
     Double v = (Double) o; 
     System.out.println(v); 
    } 
} 
+0

所以你的回答應該是否定的。它不會導致不可預知的問題,如果您還記得在整個項目中將「Float」更改爲「Double」。 – Oran 2014-08-27 15:48:46

+0

@Onn'float'!='Float','double'!='Double'。它也可能會受到期望其他類型的第三方庫的影響。 – 2014-08-27 15:49:57

+0

我對運行時錯誤感興趣,而不是編譯錯誤 – 2014-08-27 15:52:29

2

另一個區別是,不像float,寫入到非易失性double字段不保證是原子。

這是一種不太可能的情況,它只會影響沒有正確同步的多線程系統,但男孩會引起意外的運行時問題。

1

請注意,即使您將浮動更改爲雙打,您仍然會發生舍入錯誤。例如:假設我們設置了i到3703816849309525656(= 3 * 0x1122334455667788,這只是我試過的一個數字)。

long i = 3703816849309525656L; 
float multiplier = 1.3f; 
i *= multiplier; 
System.out.println(i); 

輸出

4814961529147359232 

long i = 3703816849309525656L; 
double multiplier = 1.3; 
i *= multiplier; 
System.out.println(i); 

輸出

4814961904102383616 

但使用計算器程序(GNU bc):

(3703816849309525656 * 13)/10 
4814961904102383352.8 

所以使用double讓你一個LO接近,但結果仍然不正確;當一個人處理整數時,通常需要準確的結果。因此,我會考慮使用BigIntegerBigDecimal,但我意識到這種變化需要更多的努力。