下面我将详细介绍几种转换方法、它们的区别、使用场景以及注意事项。

核心转换方法
主要有两种官方推荐的转换方法:强制类型转换 和 Math 类的方法。
强制类型转换 (long)
这是最直接、最快速的方法,它通过直接截断小数部分来转换。
语法
long value = (long) doubleValue;
工作原理
强制类型转换会直接丢弃 double 的小数部分,只保留整数部分,这相当于向零舍入(Rounding towards zero)。
doubleValue是正数,它会直接去掉小数部分。doubleValue是负数,它也会直接去掉小数部分(这相当于向零靠拢)。
示例代码
public class DoubleToLongCast {
public static void main(String[] args) {
double positiveDouble = 123.45;
double negativeDouble = -123.45;
double doubleWithZeroFraction = 100.0;
// 强制类型转换
long positiveLong = (long) positiveDouble;
long negativeLong = (long) negativeDouble;
long zeroFractionLong = (long) doubleWithZeroFraction;
System.out.println("原始 double 值: " + positiveDouble + " -> 转换后 long 值: " + positiveLong);
System.out.println("原始 double 值: " + negativeDouble + " -> 转换后 long 值: " + negativeLong);
System.out.println("原始 double 值: " + doubleWithZeroFraction + " -> 转换后 long 值: " + zeroFractionLong);
}
}
输出结果
原始 double 值: 123.45 -> 转换后 long 值: 123
原始 double 值: -123.45 -> 转换后 long 值: -123
原始 double 值: 100.0 -> 转换后 long 值: 100
Math.round()
如果你希望在转换前对小数部分进行四舍五入,而不是直接截断,那么应该使用 Math.round() 方法。

语法
long value = Math.round(doubleValue);
工作原理
Math.round() 会根据 double 值的小数部分进行四舍五入,然后返回最接近的 long 值。
- 如果小数部分 >= 0.5,则向正无穷方向舍入(即向上取整)。
- 如果小数部分 < 0.5,则向负无穷方向舍入(即向下取整)。
示例代码
public class DoubleToLongRound {
public static void main(String[] args) {
double double1 = 123.49;
double double2 = 123.50;
double double3 = -123.49;
double double4 = -123.50;
// 使用 Math.round()
long long1 = Math.round(double1);
long long2 = Math.round(double2);
long long3 = Math.round(double3);
long long4 = Math.round(double4);
System.out.println("原始 double 值: " + double1 + " -> 四舍五入后 long 值: " + long1);
System.out.println("原始 double 值: " + double2 + " -> 四舍五入后 long 值: " + long2);
System.out.println("原始 double 值: " + double3 + " -> 四舍五入后 long 值: " + long3);
System.out.println("原始 double 值: " + double4 + " -> 四舍五入后 long 值: " + long4);
}
}
输出结果
原始 double 值: 123.49 -> 四舍五入后 long 值: 123
原始 double 值: 123.5 -> 四舍五入后 long 值: 124
原始 double 值: -123.49 -> 四舍五入后 long 值: -123
原始 double 值: -123.5 -> 四舍五入后 long 值: -124 // 注意:Java 8+ 中 -0.5 会向远离零的方向舍入
注意:在 Java 8 之前,
Math.round(-0.5)的结果是0,从 Java 8 开始,Math.round()的舍入行为遵循了 IEEE 754 标准,即“四舍六入五成双”,但在处理-0.5这种情况时,它会向远离零的方向舍入(即-1)。
Math.floor() 和 Math.ceil()
有时你需要更精确的控制,比如总是向下取整或总是向上取整。
Math.floor() - 向下取整
返回小于或等于参数的最大 double 值,然后需要再强制转换为 long。

double d = 123.99; long result = (long) Math.floor(d); // 结果是 123
Math.ceil() - 向上取整
返回大于或等于参数的最小 double 值,然后需要再强制转换为 long。
double d = 123.01; long result = (long) Math.ceil(d); // 结果是 124
重要注意事项
精度问题(double 的局限性)
double 是一个 64 位的浮点数,它用二进制科学计数法来表示数字,这意味着很多十进制小数无法被精确表示。
示例:
double value = 123456789012345.67;
long result = (long) value; // 强制转换
System.out.println("原始 double: " + value); // 输出可能是 1.2345678901234567E14
System.out.println("转换后 long: " + result); // 输出可能是 123456789012456
你会发现转换后的 long 值与原始 double 值的整数部分不符,这是因为 value 变量本身在存储时就已经因为精度限制而失真了。
double 值非常大(超出 long 的精确表示范围)或者它本身就是一个不精确的十进制小数,那么转换结果可能不是你期望的,在处理金融或高精度计算时,应避免使用 double,而应使用 BigDecimal。
数值溢出
long 的范围是 -2^63 到 2^63-1。double 值超出了这个范围,转换行为会变得特殊。
double值大于Long.MAX_VALUE,强制转换会返回Long.MAX_VALUE。double值小于Long.MIN_VALUE,强制转换会返回Long.MIN_VALUE。
Math.round() 也会遵循同样的溢出规则。
double tooBig = Double.MAX_VALUE;
double tooSmall = -Double.MAX_VALUE;
System.out.println("(long) " + tooBig + " = " + (long) tooBig); // 输出 9223372036854775807 (Long.MAX_VALUE)
System.out.println("(long) " + tooSmall + " = " + (long) tooSmall); // 输出 -9223372036854775808 (Long.MIN_VALUE)
总结与选择
| 方法 | 舍入方式 | 使用场景 |
|---|---|---|
(long) d |
直接截断(向零舍入) | 当你明确知道只需要丢弃小数部分时,从 999 中获取 123,性能最好。 |
Math.round(d) |
四舍五入 | 当你需要根据标准四舍五入规则将浮点数转换为最接近的整数时,这是最常见的“四舍五入”需求。 |
(long) Math.floor(d) |
向下取整 | 当你需要总是取比当前数小的最大整数时,计算页数时 (totalItems / itemsPerPage)。 |
(long) Math.ceil(d) |
向上取整 | 当你需要总是取比当前数大的最小整数时,确保分配足够资源。 |
- 想要丢弃小数部分,用
(long)。 - 想要四舍五入,用
Math.round()。 - 需要精确控制舍入方向,用
Math.floor()或Math.ceil()。 - 对精度要求极高,请考虑使用
BigDecimal。
