Java Explicit Cast 从 Double 到 Int 的舍入规则是什么

What are the rounding rules of Java Explicit Cast from Double to Int

提问人:Evloution78 提问时间:10/25/2023 更新时间:10/25/2023 访问量:51

问:

今天在演示 Java 显式类型转换时遇到了一个奇怪的怪癖,我想知道为什么会发生这种情况。

如果我将双精度转换为整数,并且我的数字是 .9 到 16 精度,它将四舍五入。(请参阅代码中的注释)如果我使它达到 15 精度,它会向下舍入。

同样,如果我把我的数字 .8...它仍然会向下舍入。

        double a = 5.9999999999999999;// 16 precision rounds to 6
        double a1 = 5.8888888888888888; // 16 precision rounds to 5
        double b = 5.999999999999999;// 15 precision rounds to 5
        double c = 5.111111111111111111111111111111111111111; //rounds to 5
        int cast = (int)a;
        for (int i = 0 ; i < 1000000 ; i++){
            System.out.print(cast);
        }

最初以为我溢出了 int,但似乎并非如此。

有什么想法吗?

Java 强制转换 精度整数

评论

2赞 Andy Turner 10/25/2023
为什么打印这么多次?你认为它会改变吗?cast
0赞 Reilas 10/25/2023
使用 BigDecimal 类。
0赞 user207421 10/25/2023
首先,这些值都不是精确的。
0赞 Evloution78 10/25/2023
@AndyTurner我的意思是,不,但后来我想这可能是一个奇怪的编译错误,所以我最好打印很多次,以确保我得到一致的结果。
0赞 Evloution78 10/25/2023
@user207421我理解这一点,只是举了选角的例子,然后遇到了这种情况,以前从未遇到过这种情况

答:

2赞 Andy Turner 10/25/2023 #1

这与强制转换为 无关。int

如果打印 的值:a

double a = 5.9999999999999999;
System.out.println(a);

它打印 .6.0

这是因为 double 的精度有限,不能精确表示文本值。

2赞 rgettman 10/25/2023 #2

根据 JLS 第 5.1.3 节,涉及从浮点类型到整数类型的缩小基元转换的转换将四舍五入为零:

将浮点数缩小为整型 T 的转换需要两个步骤:

  1. 在第一步中,如果 T 为 long,则将浮点数转换为 long,如果 T 为 byte、short、char 或 int,则转换为 int,如下所示:
  • 如果浮点数为 NaN (§4.2.3),则转换第一步的结果为 int 或 long 0。
  • 否则,如果浮点数不是无穷大,则使用向零舍入策略 (§4.2.4) 将浮点值舍入为整数值 V。

那么为什么看似四舍五入呢?必须先将文本转换为值。JLS (3.10.2) 的 Floating-Point Literals 部分对此进行了介绍:double a = 5.9999999999999999;doubledouble

对于包 java.lang 的 Float 类和 Double 类的方法 valueOf 描述了从浮点数的 Unicode 字符串表示形式到内部 IEEE 754 二进制浮点表示形式的正确输入转换的详细信息。

好的,让我们转到 Value Of for Double

[字符串值]被视为在通常的“计算机化科学记数法”中表示精确的十进制值或精确的十六进制值;然后,这个精确的数值在概念上被转换为一个“无限精确”的二进制值,然后按照 IEEE 754 浮点运算的通常舍入到最接近规则四舍五入为类型,其中包括保留零值的符号。double

(粗体强调我的)

在超出小数点的 16 位精度(有 17 个包含点)时,您正在突破文字的精度极限。此时,比下一个较低的值更接近。5double5.99999999999999996double

因此,之所以显示 6,是因为浮点文字在转换为 之前被舍入为 a而转换为 an 是您看到打印的 6。6.0doubleint6.0int

您拥有的其他值不会一直四舍五入为文字,因此强制转换将其一直缩小到 5。6.0doubleint