杰瑞科技汇

Java double转int为何会精度丢失?

核心区别

方法 描述 处理小数部分 示例 (double d = 3.7;)
强制类型转换 (int) 直接截断,只保留整数部分,丢弃所有小数。 直接丢弃 (int) d 的结果是 3
Math.floor() 向下取整,返回小于或等于该 double 的最大整数。 向下舍入 Math.floor(d) 的结果是 0,再转 int3
Math.ceil() 向上取整,返回大于或等于该 double 的最小整数。 向上舍入 Math.ceil(d) 的结果是 0,再转 int4
Math.round() 四舍五入,返回最接近的 long 值,再转 int 四舍五入 Math.round(d) 的结果是 4L,再转 int4

强制类型转换 (int)

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

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

语法:

int myInt = (int) myDouble;

特点:

  • 简单快捷:这是 JVM 支持的原生操作,性能最高。
  • 直接截断:它不是四舍五入,而是直接“砍掉”小数部分。

示例代码:

public class DoubleToIntExample {
    public static void main(String[] args) {
        double positiveDouble = 123.45;
        double negativeDouble = -123.45;
        // 强制类型转换
        int positiveInt = (int) positiveDouble;
        int negativeInt = (int) negativeDouble;
        System.out.println("原始 double 值: " + positiveDouble);
        System.out.println("强制转换后 int 值: " + positiveInt); // 输出 123
        System.out.println("原始 double 值: " + negativeDouble);
        System.out.println("强制转换后 int 值: " + negativeInt); // 输出 -123
    }
}

输出:

Java double转int为何会精度丢失?-图2
(图片来源网络,侵删)
原始 double 值: 123.45
强制转换后 int 值: 123
原始 double 值: -123.45
强制转换后 int 值: -123

注意:-123.45 转换后是 -123,而不是 -124,因为它是直接截断小数部分。


使用 java.lang.Math 类的方法

当你需要更复杂的舍入逻辑时(如四舍五入、向上取整、向下取整),应该使用 Math 类中的方法,这些方法返回的是 doublelong 类型,所以通常需要再进行一次类型转换。

Math.floor() - 向下取整

返回小于或等于参数的最大 double 值,并等于一个整数。

语法:

Java double转int为何会精度丢失?-图3
(图片来源网络,侵删)
int myInt = (int) Math.floor(myDouble);

示例:

double d1 = 3.7;
double d2 = 3.2;
double d3 = -3.7;
System.out.println((int) Math.floor(d1)); // 输出 3
System.out.println((int) Math.floor(d2)); // 输出 3
System.out.println((int) Math.floor(d3)); // 输出 -4 (因为 -4 < -3.7)

Math.ceil() - 向上取整

返回大于或等于参数的最小 double 值,并等于一个整数。

语法:

int myInt = (int) Math.ceil(myDouble);

示例:

double d1 = 3.7;
double d2 = 3.2;
double d3 = -3.7;
System.out.println((int) Math.ceil(d1)); // 输出 4
System.out.println((int) Math.ceil(d2)); // 输出 4
System.out.println((int) Math.ceil(d3)); // 输出 -3 (因为 -3 > -3.7)

Math.round() - 四舍五入

这是最常用的舍入方法,它返回一个 long 类型,表示与参数最接近的整数。

  • 如果小数部分 >= 0.5,则向上取整。
  • 如果小数部分 < 0.5,则向下取整。

语法:

int myInt = (int) Math.round(myDouble);

示例:

double d1 = 3.7;
double d2 = 3.2;
double d3 = -3.7;
double d4 = -3.2;
System.out.println((int) Math.round(d1)); // 输出 4
System.out.println((int) Math.round(d2)); // 输出 3
System.out.println((int) Math.round(d3)); // 输出 -4 (Math.round(-3.7) 返回 -4L)
System.out.println((int) Math.round(d4)); // 输出 -3 (Math.round(-3.2) 返回 -3L)

重要注意事项

数值范围问题 (double vs int 的范围)

double 的表示范围远大于 int,如果一个 double 的值超出了 int 的表示范围(即 -2,147,483,6482,147,483,647),强制转换会导致一个不正确的值,而不会抛出异常。

示例:

double tooBig = 1.0e20; // 100,000,000,000,000,000,000
double tooSmall = -1.0e20;
int intTooBig = (int) tooBig;
int intTooSmall = (int) tooSmall;
System.out.println(tooBig + " 转换为 int 是: " + intTooBig); // 输出 2147483647 (int 的最大值)
System.out.println(tooSmall + " 转换为 int 是: " + intTooSmall); // 输出 -2147483648 (int 的最小值)

在这种情况下,转换的结果被“截断”到了 int 的边界值,如果需要进行范围检查,可以这样做:

if (myDouble > Integer.MAX_VALUE || myDouble < Integer.MIN_VALUE) {
    throw new ArithmeticException("Double value is out of int range");
}
int myInt = (int) myDouble;

浮点数精度问题

由于计算机使用二进制表示浮点数,十进制小数在二进制中可能是无限循环的,这会导致精度问题。

示例:

double d = 3.0; // 精确表示
double d2 = 3.1; // 近似表示
System.out.println((int) d);  // 输出 3
System.out.println((int) d2); // 输出 3

虽然 1 在逻辑上应该转换成 3,但如果你期望的是四舍五入,就必须使用 Math.round()

总结与如何选择

你的需求 推荐方法 原因
只需要整数部分,不关心小数 (int) myDouble 最简单、性能最高。
需要四舍五入到最近的整数 (int) Math.round(myDouble) Math.round 专门为此设计。
需要向“负无穷”方向取整 (int) Math.floor(myDouble) floor 的标准定义。
需要向“正无穷”方向取整 (int) Math.ceil(myDouble) ceil 的标准定义。

在大多数情况下,如果你只是想从 double 中得到一个整数部分,强制类型转换 (int) 是最合适的选择,如果需要舍入逻辑,则选择对应的 Math 方法。

分享:
扫描分享到社交APP
上一篇
下一篇