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() 方法。它接收一个浮点数(可以是 float,也可以是 double),并返回最接近的整数。

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.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

示例:去除多余的零

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.floor, Math.ceil, Math.rint

  • Math.floor(x) — 向下取整(取不大于 x 的最大整数),对负数同样适用。
  • Math.ceil(x) — 向上取整(取不小于 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.##" 会去掉多余的零("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
1
任务
JAVA 25 SELF, 第 6 级, 课程 4
已锁定
太空殖民地资源估算 🛰️
太空殖民地资源估算 🛰️
1
任务
JAVA 25 SELF, 第 6 级, 课程 4
已锁定
含税药剂价格的精确计算 💰
含税药剂价格的精确计算 💰
1
任务
JAVA 25 SELF, 第 6 级, 课程 4
已锁定
收入报告的美观展示 📊
收入报告的美观展示 📊
1
任务
JAVA 25 SELF, 第 6 级, 课程 4
已锁定
以友好格式显示全球销售额 🌍
以友好格式显示全球销售额 🌍
评论 (1)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
级别 21,-,Hong Kong
22 七月 2026
好多