杰瑞科技汇

double转int Java会丢失精度吗?

在 Java 中,将 double 类型转换为 int 类型主要有以下几种方法,每种方法都有其特定的行为和适用场景。

double转int Java会丢失精度吗?-图1
(图片来源网络,侵删)

核心方法

强制类型转换 (Type Casting)

这是最直接、最常用的方法,它会直接截断 double 的小数部分,只保留整数部分。

语法:

int intValue = (int) doubleValue;

特点:

  • 截断而非四舍五入:它会直接丢弃小数点后的所有数字。
  • 行为
    • 对于正数,9 会变成 5
    • 对于负数,-5.9 会变成 -5(注意:不是 -6,因为截断是向零靠近)。

示例代码:

double转int Java会丢失精度吗?-图2
(图片来源网络,侵删)
public class DoubleToIntExample {
    public static void main(String[] args) {
        double positiveDouble = 99.99;
        double negativeDouble = -99.99;
        // 使用强制类型转换
        int positiveInt = (int) positiveDouble;
        int negativeInt = (int) negativeDouble;
        System.out.println("原始 double 值: " + positiveDouble + " -> 转换后的 int 值: " + positiveInt);
        System.out.println("原始 double 值: " + negativeDouble + " -> 转换后的 int 值: " + negativeInt);
    }
}

输出:

原始 double 值: 99.99 -> 转换后的 int 值: 99
原始 double 值: -99.99 -> 转换后的 int 值: -99

Math.floor() 方法

这个方法会返回小于或等于给定 double 值的最大整数,这相当于向负无穷方向取整。

语法:

int intValue = (int) Math.floor(doubleValue);

特点:

double转int Java会丢失精度吗?-图3
(图片来源网络,侵删)
  • 向下取整:无论正负,都向数值更小的方向取整。
  • 行为
    • 对于正数,9 会变成 5
    • 对于负数,-5.9 会变成 -6

示例代码:

public class MathFloorExample {
    public static void main(String[] args) {
        double positiveDouble = 5.9;
        double negativeDouble = -5.9;
        // 使用 Math.floor
        int positiveInt = (int) Math.floor(positiveDouble);
        int negativeInt = (int) Math.floor(negativeDouble);
        System.out.println("原始 double 值: " + positiveDouble + " -> floor 后的 int 值: " + positiveInt);
        System.out.println("原始 double 值: " + negativeDouble + " -> floor 后的 int 值: " + negativeInt);
    }
}

输出:

原始 double 值: 5.9 -> floor 后的 int 值: 5
原始 double 值: -5.9 -> floor 后的 int 值: -6

Math.ceil() 方法

这个方法会返回大于或等于给定 double 值的最小整数,这相当于向正无穷方向取整。

语法:

int intValue = (int) Math.ceil(doubleValue);

特点:

  • 向上取整:无论正负,都向数值更大的方向取整。
  • 行为
    • 对于正数,1 会变成 6
    • 对于负数,-5.1 会变成 -5

示例代码:

public class MathCeilExample {
    public static void main(String[] args) {
        double positiveDouble = 5.1;
        double negativeDouble = -5.1;
        // 使用 Math.ceil
        int positiveInt = (int) Math.ceil(positiveDouble);
        int negativeInt = (int) Math.ceil(negativeDouble);
        System.out.println("原始 double 值: " + positiveDouble + " -> ceil 后的 int 值: " + positiveInt);
        System.out.println("原始 double 值: " + negativeDouble + " -> ceil 后的 int 值: " + negativeInt);
    }
}

输出:

原始 double 值: 5.1 -> ceil 后的 int 值: 6
原始 double 值: -5.1 -> ceil 后的 int 值: -5

Math.round() 方法

这个方法会返回最接近的 longint 值,并根据小数部分进行四舍五入。

语法:

  • 返回 long (适用于大数值):
    long longValue = Math.round(doubleValue);
  • 转换为 int:
    int intValue = (int) Math.round(doubleValue);

特点:

  • 四舍五入:这是最符合常规数学取整规则的方法。
  • 舍入规则
    • 小数部分 >= 0.5,则向绝对值更大的方向取整。
    • 小数部分 < 0.5,则向绝对值更小的方向取整。
  • 行为
    • 4 -> 5
    • 5 -> 6 (注意:Java 8开始,5.5会向偶数取整为6,而5.5向偶数取整为6,4.5向偶数取整为4,这是“银行家舍入法”)
    • -5.4 -> -5
    • -5.5 -> -6

示例代码:

public class MathRoundExample {
    public static void main(String[] args) {
        double d1 = 5.4;
        double d2 = 5.5;
        double d3 = -5.4;
        double d4 = -5.5;
        // 使用 Math.round
        int i1 = (int) Math.round(d1);
        int i2 = (int) Math.round(d2);
        int i3 = (int) Math.round(d3);
        int i4 = (int) Math.round(d4);
        System.out.println("原始 double 值: " + d1 + " -> round 后的 int 值: " + i1);
        System.out.println("原始 double 值: " + d2 + " -> round 后的 int 值: " + i2);
        System.out.println("原始 double 值: " + d3 + " -> round 后的 int 值: " + i3);
        System.out.println("原始 double 值: " + d4 + " -> round 后的 int 值: " + i4);
    }
}

输出:

原始 double 值: 5.4 -> round 后的 int 值: 5
原始 double 值: 5.5 -> round 后的 int 值: 6
原始 double 值: -5.4 -> round 后的 int 值: -5
原始 double 值: -5.5 -> round 后的 int 值: -6

总结与如何选择

方法 舍入/转换规则 示例 (9) 示例 (-5.9) 适用场景
(int) 强制转换 直接截断 (向零取整) 5 -5 只需要整数部分,不关心舍入,获取像素坐标。
Math.floor() 向下取整 (向负无穷取整) 5 -6 需要向下取整的场景,例如计算不超出预算的最大购买数量。
Math.ceil() 向上取整 (向正无穷取整) 6 -5 需要向上取整的场景,例如确保有足够的容器来装所有物品。
Math.round() 四舍五入 (向最近的整数,.5向偶数取整) 6 -6 最常见的数学取整需求,如计算平均值、统计结果等。

⚠️ 重要注意事项:数据溢出

double 的值超出了 int 的表示范围时(即 double< Integer.MIN_VALUE> Integer.MAX_VALUE),以上所有方法都会发生整数溢出

  • Integer.MAX_VALUE2,147,483,647
  • Integer.MIN_VALUE-2,147,483,648

示例:

public class OverflowExample {
    public static void main(String[] args) {
        double largeDouble = 2.147483648E9; // 比 Integer.MAX_VALUE 大
        double smallDouble = -2.147483649E9; // 比 Integer.MIN_VALUE 小
        // 强制转换会溢出
        int largeInt = (int) largeDouble; // 结果会是负数
        int smallInt = (int) smallDouble; // 结果会是正数
        System.out.println("原始 double: " + largeDouble + " -> 转换后 int: " + largeInt);
        System.out.println("原始 double: " + smallDouble + " -> 转换后 int: " + smallInt);
    }
}

输出:

原始 double: 2.147483648E9 -> 转换后 int: -2147483648
原始 double: -2.147483649E9 -> 转换后 int: 2147483647

这显然是错误的结果,在进行转换前,最好先检查一下范围。

如何安全地处理溢出(Java 8+)

如果你使用的是 Java 8 或更高版本,可以使用 Math 类中的 toIntExact() 方法,它在转换失败时会抛出 ArithmeticException,从而让你明确地知道发生了溢出。

public class SafeConversionExample {
    public static void main(String[] args) {
        double safeDouble = 123.456;
        double overflowDouble = 2.147483648E9;
        // 安全转换
        try {
            int safeInt = Math.toIntExact((long) Math.round(safeDouble)); // 先转为 long 再用 toIntExact
            System.out.println("安全转换成功: " + safeInt);
        } catch (ArithmeticException e) {
            System.out.println("转换失败,数值过大或过小: " + e.getMessage());
        }
        // 会触发溢出异常
        try {
            // Math.toIntExact 接受 long,所以我们需要先 round
            int overflowInt = Math.toIntExact((long) Math.round(overflowDouble));
            System.out.println("安全转换成功: " + overflowInt);
        } catch (ArithmeticException e) {
            System.out.println("转换失败,数值过大或过小: " + e.getMessage());
        }
    }
}

输出:

安全转换成功: 123
转换失败,数值过大或过小: integer overflow

最终建议

  1. 如果你只需要简单地丢弃小数部分,使用 强制转换 (int),这是最高效的。
  2. 如果你需要标准的四舍五入,使用 Math.round()
  3. 如果你的业务逻辑需要向上或向下取整,使用 Math.ceil()Math.floor()
  4. 在处理可能超出 int 范围的大数值时,务必进行范围检查,或者使用 Math.toIntExact() 来安全地捕获溢出异常。
分享:
扫描分享到社交APP
上一篇
下一篇