要在Java中對小數做處理,不得不提到BigDecimal這個類別,使用它的setScale方法,就可以得到想要的小數點處理。
如,要做四捨五入:
package idv.jk.math; import java.math.BigDecimal; public class BigDecimalEx { public static void main(String... args){ double a = 3.454; double b = new BigDecimal(a) .setScale(1, BigDecimal.ROUND_HALF_UP) .doubleValue(); System.out.println("四捨五入到小數點下一位: " + b); b = new BigDecimal(a) .setScale(2, BigDecimal.ROUND_HALF_UP) .doubleValue(); System.out.println("四捨五入到小數點下二位: " + b); } }
得到的結果:
四捨五入到小數點下一位: 3.5 四捨五入到小數點下二位: 3.45
在setScale中,傳入的第一個參數為要進位的小數點位數,第二個參數表示進位時的方式,如上例就是我們熟知的「四捨五入」,當要捨去的位數為「>= 5」時,就進位,詳細請見Java Doc。
大概知道用法後,來看一個令拜歐一度視為「玄學」的現象:
package idv.jk.math; import java.math.BigDecimal; public class BigDecimalEx { public static void main(String... args){ double a = 3.45; double b = new BigDecimal(a) .setScale(1, BigDecimal.ROUND_HALF_UP) .doubleValue(); System.out.println("四捨五入(ROUND_HALF_UP)到小數點下一位: " + b); b = new BigDecimal(a) .setScale(1, BigDecimal.ROUND_HALF_DOWN) .doubleValue(); System.out.println("四捨五入(ROUND_HALF_DOWN)到小數點下一位: " + b); } }
在上列程式碼第17行的地方,拜歐將參數改成BigDecimal.ROUND_HALF_DOWN,在Java Doc中,若在setScale使用此參數,則捨去的部位要「> 5」才會做進位,所以「3.45」使用此參數,要進位到小數點下一位,應該是「3.4」,但程式執行得到的結果卻是:
四拾五入(ROUND_HALF_UP)到小數點下一位: 3.5 四拾五入(ROUND_HALF_DOWN)到小數點下一位: 3.5
去看了一下BigDecimal中的建構方法中有提到:你宣告一個double變數出來丟進BigDecimal中的建構方法中,如上列的「3.45」,但在Java中,「3.45」真正的值是「3.4500000000000000....555...」,所以上列程式捨去的部份是「> 5」的。
若你要精確地建構「3.45」的BigDecimal物件,就要用new BigDecimal(String str)這個建構方法,如:
package idv.jk.math; import java.math.BigDecimal; public class BigDecimalEx { public static void main(String... args){ String a = "3.45"; double b = new BigDecimal(a) .setScale(1, BigDecimal.ROUND_HALF_UP) .doubleValue(); System.out.println("四捨五入(ROUND_HALF_UP)到小數點下一位: " + b); b = new BigDecimal(a) .setScale(1, BigDecimal.ROUND_HALF_DOWN) .doubleValue(); System.out.println("四捨五入(ROUND_HALF_DOWN)到小數點下一位: " + b); } }
執行結果:
四捨五入(ROUND_HALF_UP)到小數點下一位: 3.5 四捨五入(ROUND_HALF_DOWN)到小數點下一位: 3.4