CodeGym /Các khóa học /JAVA 25 SELF /Làm tròn và định dạng số

Làm tròn và định dạng số

JAVA 25 SELF
Mức độ , Bài học
Có sẵn

1. Giới thiệu

Trong thực tế, hiếm khi chúng ta cần thấy phần thập phân “dài lê thê”. Ví dụ, khi bạn tính giá hàng hóa, lương, điểm trung bình hoặc diện tích phòng — thường chỉ cần vài chữ số thập phân, chứ không phải 15 chữ số.

Ví dụ, kết quả phép chia:

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

Người dùng khi thấy kết quả như vậy có thể hoang mang và nghĩ chương trình bị lỗi. Vì thế, ta thường cần làm tròn số — đến số nguyên gần nhất, đến hai chữ số thập phân, v.v.

Trong Java có một số công cụ tiện lợi để làm việc này.

2. Phương thức Math.round(): làm tròn đến số nguyên gần nhất

Cách đơn giản nhất để làm tròn là dùng phương thức Math.round(). Nó nhận một số dấu phẩy động (cả float lẫn double) và trả về số nguyên gần nhất.

Cách Math.round hoạt động

  • Nếu phần thập phân nhỏ hơn 0.5 — làm tròn xuống.
  • Nếu phần thập phân 0.5 hoặc lớn hơn — làm tròn lên.

Ví dụ:

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

Kiểu giá trị trả về

  • Nếu truyền vào float, sẽ trả về int.
  • Nếu truyền vào double, sẽ trả về long.
float f = 5.8f;
int roundedF = Math.round(f); // 6

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

Lưu ý: đôi khi điều này gây bất ngờ — làm tròn double mà lại nhận long! Nếu bạn cần int, hãy ép kiểu tường minh:

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

3. Làm tròn đến số chữ số thập phân mong muốn

Thường ta cần làm tròn không phải đến số nguyên, mà ví dụ, đến hai chữ số thập phân (cho tiền tệ, phần trăm, v.v.).

Trong Java không có phương thức “ma thuật” kiểu Math.roundTo2Digits(), nhưng ta có thể tự thực hiện.

Cách 1: mẹo toán học với nhân và chia

  1. Nhân số với 100 (nếu cần hai chữ số).
  2. Làm tròn đến số nguyên bằng Math.round.
  3. Chia ngược lại cho 100.

Ví dụ:

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

Cách hoạt động:

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

4. Định dạng số: lớp DecimalFormat

Đôi khi không chỉ cần làm tròn, mà còn cần hiển thị số một cách đẹp mắt — với số chữ số thập phân xác định, số 0 ở đầu, dấu phân tách hàng nghìn, v.v. Để làm việc này trong Java có lớp DecimalFormat thuộc gói java.text.

Cách DecimalFormat hoạt động

  1. Tạo đối tượng với mẫu mong muốn.
  2. Gọi phương thức format(...).
import java.text.DecimalFormat;

double value = 3.14159;

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

Cấu trúc mẫu

  • "0.00" — luôn có hai chữ số thập phân (kể cả khi số là số nguyên).
  • "0.###" — tối đa ba chữ số thập phân, các số 0 dư sẽ không hiển thị.
  • "#,##0.00" — thêm dấu phân tách hàng nghìn (ví dụ "1,234.56").

Ví dụ các mẫu khác nhau:

Mẫu Số Kết quả
"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

Ví dụ với dấu phân tách hàng nghìn

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

Ví dụ: hiển thị không có số 0 thừa

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. Định dạng bằng String.format

Đôi khi cho các trường hợp đơn giản, dùng String.format rất tiện — cách định dạng chuỗi dựng sẵn, tương tự printf trong các ngôn ngữ khác.

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

Ở đây "%.2f" — nghĩa là “in số với hai chữ số thập phân”.

So sánh cách tiếp cận:

  • DecimalFormat — mạnh hơn, hỗ trợ mẫu và bản địa hóa, tiện cho dấu phân tách hàng nghìn.
  • String.format — đơn giản hơn khi chỉ cần quy định số chữ số thập phân.

6. Những đặc điểm khi làm tròn: Math.floor, Math.ceil, Math.rint

  • Math.floor(x) — làm tròn xuống (về phía nhỏ hơn), kể cả với số âm.
  • Math.ceil(x) — làm tròn lên (về phía lớn hơn).
  • Math.rint(x) — làm tròn đến số nguyên gần nhất, nhưng trả về double.

Ví dụ:

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 (đúng vậy, không phải lỗi đánh máy!)
System.out.println(Math.rint(3.5));  // 4.0

Chú ý: Math.rint đôi khi làm tròn “về số chẵn gần nhất” — quy tắc này (còn gọi là banker's rounding) giúp giảm tích lũy sai số trong tính toán hàng loạt.

7. Những điểm hữu ích

Trực quan: bảng làm tròn

Số 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

Làm tròn không phải là định dạng!

Rất quan trọng phải hiểu sự khác biệt giữa làm trònđịnh dạng.

  • Làm tròn — thay đổi giá trị của số (ví dụ, 2.7182.72).
  • Định dạng — thay đổi cách số hiển thị khi in ra (ví dụ, 2.718"2.72" trên màn hình, nhưng trong bộ nhớ vẫn là 2.718).
double x = 2.718;
System.out.println(String.format("%.2f", x)); // 2.72
System.out.println(x); // 2.718

Nếu bạn muốn dùng số đã làm tròn trong các phép tính tiếp theo — hãy làm tròn theo toán học! Nếu chỉ để hiển thị — hãy định dạng.

8. Những lỗi thường gặp khi làm tròn và định dạng số

Lỗi số 1: Chỉ làm tròn khi hiển thị, nhưng sau đó lại dùng số “có đuôi”.
Tình huống rất hay gặp — in ra màn hình giá trị đã định dạng đẹp, rồi tiếp tục dùng số gốc “dài” cho tính toán. Với tiền bạc, điểm số và các kết quả tổng — hãy làm tròn trước (ví dụ dùng Math.round hoặc mẹo nhân/chia), rồi mới lưu/trả cho người dùng.

Lỗi số 2: Kỳ vọng Math.round(x) trả về double với hai chữ số thập phân.
Math.round() luôn làm tròn đến số nguyên gần nhất: với float trả về int, với doublelong. Để có hai chữ số thập phân, hãy dùng cách nhân/chia hoặc định dạng.

Lỗi số 3: Dùng DecimalFormat cho tính toán.
DecimalFormat.format() trả về chuỗi. Không thể dùng chuỗi trong số học: bạn sẽ gặp lỗi biên dịch hoặc NumberFormatException khi phân tích ngược trở lại.

Lỗi số 4: Mẫu DecimalFormat không đúng.
Mẫu phải khớp kỳ vọng: "0.00" luôn hiển thị hai chữ số ("2.00"), còn "0.##" sẽ bỏ các số 0 dư ("2", "2.1", "2.12").

Lỗi số 5: Mất độ chính xác khi chia cho 100.
Nếu bạn chia int cho int, kết quả cũng là int!

int a = 5;
System.out.println(a / 2); // 2, chứ không phải 2.5!

Để phép chia là “số thực”, ít nhất một toán hạng phải là double:

int a = 5;
System.out.println(a / 2.0); // 2.5
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION