java對小數四捨五入、DecimalFormat對數值格式化的舍入問題——RoundingMode

背景:
在對數值做一些計算的時候,往往我們需要控制計算結果的精度,所以會使用到DecimalFormat類來將數值格式化成字符串。在最近測試中,突然注意到默認使用DecimalFormat進行格式化時,並非我們一般認識上的四捨五入,而是一種詭異的舍入——(1)5以下捨去(2)5以上舍入(3)若前一位是奇數,5就舍入(4)如前一位是偶數,5就捨去

遇到這樣的統計結論,沒有理論的支持,我們總是感到很迷茫,所以我仔細查閱了DecimalFormat相關API,終於找到了答案。

 

分析:
在DecimalFormat API中有這樣一段:

舍入

DecimalFormat 提供 RoundingMode 中定義的舍入模式進行格式化。默認情況下,它使用RoundingMode.HALF_EVEN。

這句話指出了舍入模式有多種類型,而DecimalFormat默認採用了RoundingMode.HALF_EVEN這種類型,接下來,我們就一起看看,到底存在哪些舍入類型吧

 

RoundingMode介紹:
RoundingMode是一個枚舉類,有一下幾個常量:UP,DOWN,CEILING,FLOOR,HALF_UP,HALF_DOWN,HALF_EVEN,UNNECESSARY

 

 

UP
public static final RoundingMode UP
遠離零方向舍入的舍入模式。始終對非零捨棄部分前面的數字加 1。注意,此舍入模式始終不會減少計算值的絕對值。
示例:

輸入數字    使用 UP 舍入模式
將輸入數字舍入爲一位數
5.5    6
2.5    3
1.6    2
1.1    2
1.0    1
-1.0    -1
-1.1    -2
-1.6    -2
-2.5    -3
-5.5    -6
 

 

DOWN
public static final RoundingMode DOWN
向零方向舍入的舍入模式。從不對捨棄部分前面的數字加 1(即截尾)。注意,此舍入模式始終不會增加計算值的絕對值。
示例:

輸入數字    使用 DOWN 舍入模式
將輸入數字舍入爲一位數
5.5    5
2.5    2
1.6    1
1.1    1
1.0    1
-1.0    -1
-1.1    -1
-1.6    -1
-2.5    -2
-5.5    -5
 

 

CEILING
public static final RoundingMode CEILING
向正無限大方向舍入的舍入模式。如果結果爲正,則舍入行爲類似於 RoundingMode.UP;如果結果爲負,則舍入行爲類似於 RoundingMode.DOWN。注意,此舍入模式始終不會減少計算值。
示例:

輸入數字    使用 CEILING 舍入模式
將輸入數字舍入爲一位數
5.5    6
2.5    3
1.6    2
1.1    2
1.0    1
-1.0    -1
-1.1    -1
-1.6    -1
-2.5    -2
-5.5    -5
 

 

FLOOR
public static final RoundingMode FLOOR
向負無限大方向舍入的舍入模式。如果結果爲正,則舍入行爲類似於 RoundingMode.DOWN;如果結果爲負,則舍入行爲類似於RoundingMode.UP。注意,此舍入模式始終不會增加計算值。
示例:

輸入數字    使用 FLOOR 舍入模式
將輸入數字舍入爲一位數
5.5    5
2.5    2
1.6    1
1.1    1
1.0    1
-1.0    -1
-1.1    -2
-1.6    -2
-2.5    -3
-5.5    -6
 

 

HALF_UP
public static final RoundingMode HALF_UP
向最接近數字方向舍入的舍入模式,如果與兩個相鄰數字的距離相等,則向上舍入。如果被捨棄部分 >= 0.5,則舍入行爲同 RoundingMode.UP;否則舍入行爲同RoundingMode.DOWN。注意,此舍入模式就是通常學校裏講的四捨五入。
示例:

輸入數字    使用 HALF_UP 舍入模式
將輸入數字舍入爲一位數
5.5    6
2.5    3
1.6    2
1.1    1
1.0    1
-1.0    -1
-1.1    -1
-1.6    -2
-2.5    -3
-5.5    -6
 

 

HALF_DOWN
public static final RoundingMode HALF_DOWN
向最接近數字方向舍入的舍入模式,如果與兩個相鄰數字的距離相等,則向下舍入。如果被捨棄部分 > 0.5,則舍入行爲同 RoundingMode.UP;否則舍入行爲同RoundingMode.DOWN。
示例:

輸入數字    使用 HALF_DOWN 舍入模式
將輸入數字舍入爲一位數
5.5    5
2.5    2
1.6    2
1.1    1
1.0    1
-1.0    -1
-1.1    -1
-1.6    -2
-2.5    -2
-5.5    -5
 

 

HALF_EVEN
public static final RoundingMode HALF_EVEN
向最接近數字方向舍入的舍入模式,如果與兩個相鄰數字的距離相等,則向相鄰的偶數舍入。如果捨棄部分左邊的數字爲奇數,則舍入行爲同 RoundingMode.HALF_UP;如果爲偶數,則舍入行爲同RoundingMode.HALF_DOWN。注意,在重複進行一系列計算時,此舍入模式可以在統計上將累加錯誤減到最小。此舍入模式也稱爲“銀行家舍入法”,主要在美國使用。此舍入模式類似於 Java 中對float 和double 算法使用的舍入策略。
示例:

輸入數字    使用 HALF_EVEN 舍入模式
將輸入數字舍入爲一位數
5.5    6
2.5    2
1.6    2
1.1    1
1.0    1
-1.0    -1
-1.1    -1
-1.6    -2
-2.5    -2
-5.5    -6
 

 

UNNECESSARY
public static final RoundingMode UNNECESSARY
用於斷言請求的操作具有精確結果的舍入模式,因此不需要舍入。如果對生成精確結果的操作指定此舍入模式,則拋出 ArithmeticException。
示例:

輸入數字    使用 UNNECESSARY 舍入模式
將輸入數字舍入爲一位數
5.5    拋出 ArithmeticException
2.5    拋出 ArithmeticException
1.6    拋出 ArithmeticException
1.1    拋出 ArithmeticException
1.0    1
-1.0    -1
-1.1    拋出 ArithmeticException
-1.6    拋出 ArithmeticException
-2.5    拋出 ArithmeticException
-5.5    拋出 ArithmeticException

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章