杰瑞科技汇

Java double转long精度如何处理?

Java 会直接截断 double 的小数部分,而不是进行四舍五入,然后将整数部分赋值给 long 变量。

Java double转long精度如何处理?-图1
(图片来源网络,侵删)

下面我将从核心方法、注意事项、完整代码示例和最佳实践几个方面详细解释。


核心转换方法

主要有两种方式可以实现 doublelong 的转换,它们在底层行为上是等价的。

强制类型转换 (Casting)

这是最直接、最常用的方法,语法是在 double 变量前加上目标类型 (long)

double myDouble = 123.45;
long myLong = (long) myDouble; // myLong 的值将是 123

工作原理: 这种转换会直接丢弃 double 值的小数部分,只保留整数部分,这个过程也称为“截断”。

Java double转long精度如何处理?-图2
(图片来源网络,侵删)

使用 longValue() 方法

Doubledouble 的包装类,它提供了一个 longValue() 方法,其效果与强制类型转换完全相同。

Double myDoubleObj = 123.45;
long myLong = myDoubleObj.longValue(); // myLong 的值将是 123

工作原理: longValue() 方法内部也是通过强制类型转换实现的,所以行为一致。


关键注意事项(非常重要!)

⚠️ 注意事项 1:精度丢失与截断

如前所述,转换是截断,不是四舍五入。

double d1 = 123.9;
double d2 = -123.9;
long l1 = (long) d1; // 结果是 123
long l2 = (long) d2; // 结果是 -123
System.out.println(l1); // 输出: 123
System.out.println(l2); // 输出: -123

可以看到,9-123.9 的小数部分都被直接丢弃了。

Java double转long精度如何处理?-图3
(图片来源网络,侵删)

⚠️ 注意事项 2:大数溢出

double 的表示范围远大于 longdouble 可以表示非常大的数(0E20),而 long 的最大值是 Long.MAX_VALUE (即 9,223,372,036,854,775,807)。

如果一个 double 的值超出了 long 的表示范围,强制转换会得到一个没有意义的值。

// double 的值远大于 long 的最大值
double tooBig = 1.0e20; // 100,000,000,000,000,000,000
long result = (long) tooBig;
System.out.println(result); // 输出一个看似随机的巨大负数: -727379968L
// 这是因为 1.0e20 的二进制表示已经超出了 long 的精度范围,导致高位信息丢失,转换后是一个错误值。

在进行转换前,最好先判断一下 double 的值是否在 long 的范围内。

⚠️ 注意事项 3:浮点数精度问题

double 是浮点数类型,它在计算机中是近似存储的,有些小数无法被精确表示。

// 0.1 在二进制中是一个无限循环小数,无法精确表示
double d = 0.1 + 0.2; // d 的值实际上是 0.30000000000000004
long l = (long) d; // 结果是 0
System.out.println(l); // 输出: 0

虽然这个例子中转换结果符合预期(截断后为0),但它揭示了 double 本身的不精确性,这种不精确性在转换前就已经存在了。


完整代码示例

这个示例综合了上述所有要点。

public class DoubleToLongExample {
    public static void main(String[] args) {
        System.out.println("--- 1. 基本截断 ---");
        double d1 = 123.999;
        double d2 = -456.123;
        long l1 = (long) d1;
        long l2 = (long) d2;
        System.out.println("double " + d1 + " 转换为 long: " + l1); // 输出 123
        System.out.println("double " + d2 + " 转换为 long: " + l2); // 输出 -456
        System.out.println("\n--- 2. 大数溢出 ---");
        double tooBig = 1.0e30;
        long overflowResult = (long) tooBig;
        System.out.println("double " + tooBig + " 转换为 long: " + overflowResult); // 输出一个错误值
        System.out.println("\n--- 3. 浮点数精度问题 ---");
        double imprecise = 0.1 + 0.2; // 实际上是 0.30000000000000004
        long fromImprecise = (long) imprecise;
        System.out.println("double " + imprecise + " 转换为 long: " + fromImprecise); // 输出 0
        System.out.println("\n--- 4. 使用 Double.longValue() 方法 ---");
        Double myDoubleObj = 987.65;
        long l3 = myDoubleObj.longValue();
        System.out.println("Double " + myDoubleObj + " 转换为 long: " + l3); // 输出 987
    }
}

最佳实践

如果你想在转换时进行四舍五入,而不是简单的截断,你应该使用 Math 类中的辅助方法,这些方法在四舍五入前会检查是否溢出。

四舍五入

double myDouble = 123.6;
long roundedLong = Math.round(myDouble); // Math.round 返回 long
System.out.println(roundedLong); // 输出: 124
double myDouble2 = 123.4;
long roundedLong2 = Math.round(myDouble2);
System.out.println(roundedLong2); // 输出: 123

注意: Math.round() 的返回值类型是 long,所以可以直接赋值给 long 变量。

向上取整(天花板)

double myDouble = 123.1;
long ceilingLong = (long) Math.ceil(myDouble); // Math.ceil 返回 double,需要强制转换
System.out.println(ceilingLong); // 输出: 124

向下取整(地板)

double myDouble = 123.9;
long floorLong = (long) Math.floor(myDouble); // Math.floor 返回 double,需要强制转换
System.out.println(floorLong); // 输出: 123
需求 方法 说明
直接截断 (long) myDouble 最常用,直接丢弃小数部分。
直接截断 myDoubleObj.longValue() 与强制转换等价。
四舍五入 Math.round(myDouble) 推荐用于需要四舍五入的场景。
向上取整 (long) Math.ceil(myDouble) 返回不小于该数的最小整数。
向下取整 (long) Math.floor(myDouble) 返回不大于该数的最大整数。

核心建议:

  • 如果只需要整数部分,明确知道会丢失小数,使用 (long) myDouble
  • 如果需要四舍五入,请使用 Math.round()
  • 在处理可能超出 long 范围的极大 double 值时,务必小心,可能需要先进行范围检查。
分享:
扫描分享到社交APP
上一篇
下一篇