CodeGym /課程 /JAVA 25 SELF /數值的四捨五入與格式化

數值的四捨五入與格式化

JAVA 25 SELF
等級 6 , 課堂 4
開放

1. 前言

在現實生活中,很少需要看到很長的小數「尾巴」。例如計算商品價格、薪資、平均分數或房間面積時,通常只需要小數點後一兩位,而不是 15 位。

例如,除法結果:

double x = 10.0 / 3.0;
System.out.println(x); // 3.3333333333333335

使用者看到這樣的結果可能會嚇一跳,以為程式出錯了。因此我們常需要對數字進行四捨五入——到最近的整數、到小數點後兩位,等等。

Java 中有數種方便的工具可用。

2. 方法 Math.round():四捨五入到最接近的整數

最簡單的方式是使用 Math.round() 方法。它接受浮點數(可為 floatdouble),並回傳最接近的整數。

Math.round 的工作原理

  • 如果小數部分小於 0.5,則向下取整。
  • 如果小數部分為 0.5 或更大,則向上取整。

範例:

System.out.println(Math.round(2.3)); // 2
System.out.println(Math.round(2.7)); // 3
System.out.println(Math.round(2.5)); // 3
System.out.println(Math.round(-2.5)); // -2

回傳型別

  • 若傳入 float,會回傳 int
  • 若傳入 double,會回傳 long
float f = 5.8f;
int roundedF = Math.round(f); // 6

double d = 5.8;
long roundedD = Math.round(d); // 6

請注意:這有時會令人驚訝——對 double 四捨五入卻得到 long!如果你需要 int,就必須做顯式轉型:

int rounded = (int) Math.round(5.6); // 6

3. 四捨五入到指定位數的小數

常見需求不是取整,而是例如保留到小數點後兩位(用於金額、百分比等)。

在 Java 中並沒有像 Math.roundTo2Digits() 這樣的「魔法」方法,但可以手動完成。

方法 1:乘除的數學小技巧

  1. 先將數字乘以 100(如果需要兩位小數)。
  2. Math.round 取整。
  3. 再除回 100

範例:

double value = 3.14159;
double rounded = Math.round(value * 100.0) / 100.0;
System.out.println(rounded); // 3.14

運作方式:

  • 3.14159 * 100 = 314.159
  • Math.round(314.159) = 314
  • 314 / 100.0 = 3.14

4. 數值格式化:類別 DecimalFormat

有時不僅要四捨五入,還要輸出得更美觀——指定小數位數、前導零、千分位分隔等。為此,Java 提供 java.text 套件中的 DecimalFormat 類別。

DecimalFormat 怎麼用

  1. 以需要的樣式字串建立物件。
  2. 呼叫它的 format(...) 方法。
import java.text.DecimalFormat;

double value = 3.14159;

DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(value)); // 3.14

樣式字串的規則

  • "0.00" —— 總是顯示兩位小數(即便是整數)。
  • "0.###" —— 最多三位小數,多餘的 0 不輸出。
  • "#,##0.00" —— 加上千分位分隔(例如 "1,234.56")。

不同樣式的範例:

樣式 數值 結果
"0.00"
2 2.00
"0.00"
2.5 2.50
"0.00"
2.567 2.57
"0.###"
2.567 2.567
"0.###"
2.5 2.5
"#,##0.00"
12345.678 12,345.68

千分位分隔符範例

DecimalFormat df = new DecimalFormat("#,##0.00");
System.out.println(df.format(1234567.89)); // 1,234,567.89

範例:去除多餘的結尾 0

DecimalFormat df = new DecimalFormat("0.##");
System.out.println(df.format(3.1));   // 3.1
System.out.println(df.format(3.141)); // 3.14
System.out.println(df.format(3.145)); // 3.15

5. 使用 String.format 進行格式化

在簡單情況下,使用 String.format 很方便——它類似其他語言的 printf

double value = 3.14159;
System.out.println(String.format("%.2f", value)); // 3.14

這裡的 "%.2f" 表示「輸出小數點後兩位」。

方法比較:

  • DecimalFormat —— 更強大,支援樣式與在地化,適合處理千分位分隔。
  • String.format —— 較簡單,適合只需指定小數位數的情境。

6. 各種取整方法:Math.floorMath.ceilMath.rint

  • Math.floor(x) —— 向下取整(朝較小的方向),對負數也會往更小的值。
  • Math.ceil(x) —— 向上取整(朝較大的方向)。
  • Math.rint(x) —— 四捨五入到最接近的整數,但回傳 double

範例:

System.out.println(Math.floor(2.7)); // 2.0
System.out.println(Math.ceil(2.1));  // 3.0
System.out.println(Math.rint(2.5));  // 2.0 (沒錯,不是筆誤!)
System.out.println(Math.rint(3.5));  // 4.0

注意:Math.rint 有時會採用「就近偶數」的規則(亦即所謂的 banker's rounding),這能減少大量運算時的誤差累積。

7. 實用細節

視覺化:取整對照表

數值 Math.round Math.floor Math.ceil Math.rint
2.3 2 2.0 3.0 2.0
2.5 3 2.0 3.0 2.0
3.5 4 3.0 4.0 4.0
-2.3 -2 -3.0 -2.0 -2.0
-2.5 -2 -3.0 -2.0 -2.0

四捨五入不等於格式化!

務必要理解 四捨五入格式化 之間的差異。

  • 四捨五入 —— 改變數值本身(例如 2.7182.72)。
  • 格式化 —— 改變輸出時的顯示方式(例如 2.718 → 在畫面上顯示 "2.72",但記憶體內仍是 2.718)。
double x = 2.718;
System.out.println(String.format("%.2f", x)); // 2.72
System.out.println(x); // 2.718

如果你要在後續運算中使用四捨五入後的值——請用數學方式進行四捨五入!如果只是為了輸出——使用格式化即可。

8. 四捨五入與格式化的常見錯誤

錯誤 1:只在輸出時四捨五入,後續仍使用「長尾」小數。
很常見的情況是:在畫面上輸出漂亮的格式化數值,接著在計算中卻使用原始的「長」小數。對於金額、分數與總計——請先四捨五入(例如使用 Math.round 或乘除技巧),然後再儲存/傳給使用者。

錯誤 2:以為 Math.round(x) 會回傳帶有兩位小數的 double
Math.round() 總是取到最接近的整數:對 float 回傳 int,對 double 則回傳 long。若要保留兩位小數,請使用乘除法或格式化。

錯誤 3:用 DecimalFormat 來做運算。
DecimalFormat.format() 會回傳字串。不能把它拿去做算術:否則會發生編譯錯誤,或在轉回數值時丟出 NumberFormatException

錯誤 4:DecimalFormat 的樣式字串不正確。
樣式必須符合預期:"0.00" 會固定顯示兩位(例如 "2.00"),而 "0.##" 會去除多餘的 0(可能是 "2""2.1""2.12")。

錯誤 5:以 100 做整數除法造成精度損失。
如果你用 int 除以 int,結果也是 int

int a = 5;
System.out.println(a / 2); // 2,而不是 2.5!

若要做「浮點」除法,至少有一個運算元要是 double

int a = 5;
System.out.println(a / 2.0); // 2.5
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION