2016-05-13 75 views
1

爲什麼此DecimalFormat未按預期使用RoundingMode.HALF_UP進行舍入,以及應該如何獲得預期輸出?可以用DecimalFormat完成嗎?DecimalFormat即使在明確設置時也使用不正確的RoundingMode

DecimalFormat df = new DecimalFormat("0.0"); 

df.setRoundingMode(RoundingMode.HALF_UP); 

df.format(0.05); // expecting 0.1, getting 0.1 
df.format(0.15); // expecting 0.2, getting 0.1 << unexpected 

df.format(0.06); // expecting 0.1, getting 0.0 << unexpected 

我從this question看到的答案,特別是this answer,但似乎只四捨五入到整數的時候工作。

我的JDK是8.0.110,我的JRE是8.0.730.2

(以下使用Java 8回答)

你所看到的問題來自於指定代碼 「0.15」 或 「0.05」

+1

that _is_ mysterious! – tofutim

+0

也許你將不得不乘以10並再次除以變通方法 – tofutim

+1

在1.7工作正常 也許看到http://stackoverflow.com/questions/22797964/is-inconsistency-in-rounding-between-java-7 -and-java-8-a-bug –

回答

3

,當它表示爲雙精度時略小於0.15。檢查了這一點

DecimalFormat df = new DecimalFormat("#.#"); 

df.setRoundingMode(RoundingMode.HALF_UP); 

BigDecimal bd = new BigDecimal(0.15); 
System.out.println("bd=" + bd); 
System.out.println(df.format(0.15)); // expecting 0.1, getting 0.1 
bd = new BigDecimal(0.05); 
System.out.println("bd=" + bd); 
System.out.println(df.format(0.05)); 
bd = new BigDecimal(0.06); 
System.out.println("bd=" + bd); 
System.out.println(df.format(0.06)); 

這段代碼的輸出是

bd=0.1499999999999999944488848768742172978818416595458984375 
0.1 
bd=0.05000000000000000277555756156289135105907917022705078125 
0.1 
bd=0.059999999999999997779553950749686919152736663818359375 
0.1 

一個可能的解決方案(如果你確實需要它來圓的正確方法)是使用BigDecimal.valueOf創造價值。例如

BigDecimal bd = BigDecimal.valueOf(0.15); 
System.out.println("bd=" + bd); 
System.out.println(df.format(bd)); // expecting 0.1, getting 0.1 
bd = BigDecimal.valueOf(0.05); 
System.out.println("bd=" + bd); 
System.out.println(df.format(bd)); 
bd = BigDecimal.valueOf(0.06); 
System.out.println("bd=" + bd); 
System.out.println(df.format(bd)); 

現在將產生

bd=0.15 
0.2 
bd=0.05 
0.1 
bd=0.06 
0.1 

順便說一句,因爲可怕的袋熊指出,掩碼設定爲0.0,而不是#,#將0.6 0。但我認爲這是後來編輯然後當我開始看着它。使用 #。#。

+1

爲什麼downvote? :( – tofutim

+0

所以問題是'DecimalFormat df = new DecimalFormat(「0.0」);'vs'DecimalFormat df = new DecimalFormat(「#。#」);'? –

+0

@ScaryWombat他沒有這麼說。考慮到? – EJP

4

當你

df.format(0.15); 

實際上有取整運算。顯而易見的是你用df.format要求的那個,但是在編譯時會有一個更早的。

十進制值0.15不能表示爲雙精度型。雙打只能表示分母是二的冪的分母,就像十進制符號只能表示分母是十的冪的分母。當你寫0.15,編譯器幾輪這最接近的值表示爲一個雙,和值恰好是

0.1499999999999999944488848768742172978818416595458984375 

df.format正確幾輪下來。它不在0.1和0.2之間,所以HALF_UP舍入模式並不重要。

至於

df.format(0.06); // expecting 0.1, getting 0.0 << unexpected 

如果你看到,這是一個錯誤。它看起來像匹配one linked by ScaryWombat,據報道固定在8u40和8u45。使用8u51的Ideone的測試顯示了正確的行爲。更新你的Java應該可以解決這個問題。

+3

我喜歡這個:「雙打只能表示分母是兩個冪的分母」 – tofutim

+1

然後你可以解釋'df.format(0.06); //期望0.1,得到0.0「意外」 - 也就是爲什麼確定爲1.7而不是1.8? –

+1

@ user2357112在第一次提到0.05的例子之後,您是否打算使用0.0 ...而不是0.1 ...?還有,精湛的答案。 –

相關問題