2

下面代码的输出是

package com.ajay.compoitepattern;
class Test {
        public static void main(String[] args) {
                int big = 1234567890;
                float approx = big;
                System.out.println(big - (approx));
                System.out.println(big - (int)(approx));
        }
}

该程序的输出是

0.0
-46

我的问题是,如果在扩大转换中丢失了精度,那么在第一个 sysout 中也应该是 -46,为什么第一个输出是 0.0 ?

4

4 回答 4

4

第一个输出是 0.0,因为浮点数从 int 中减去,它使整个语句变为浮点数。

这意味着 int big 也转换为浮点值。基本上你正在做的是(大约 - 大约)因为(float)big = approx. 这应该是你得到零的原因。

如果你也想试试这个

System.out.println(big/(approx));

int和之间的操作float将整个语句转换为float

于 2013-07-16T04:46:58.297 回答
3

JLS §4.2.4涵盖了这一点:

如果二元运算符的至少一个操作数是浮点类型,则该运算是浮点运算,即使另一个是整数。

在您的第一个示例中,big - approx,因为approx是 a float,所以这算作浮点运算。big扩大到 a float,并且由于approxbig扩大到 a float,精度损失会自行抵消,使您得到零的答案。

在您的第二个示例中,由于您转换为big - (int) approx,因此两个操作数都不是浮点类型。现在存在精度损失,您的答案不再为零。approxint

于 2013-07-16T04:50:52.520 回答
3

float在 Java 中,尾数使用 23 位,加上 1 个隐含位,因此有 24 个有效位可用,int并由 32 位表示。因此,对于高于 2^23 的 int 值,不可避免地会损失精度。您应该double在这里使用,因为它有 53 个有效位,所以在第二种情况下结果将为 0。

public static void main(String[] args) {
    int big = 1234567890;
    double approx = big;
    System.out.println(big - (approx)); // --> 0.0
    System.out.println(big - (int) (approx)); // --> 0
}
于 2013-07-16T04:41:40.897 回答
1

阅读本文可能有助于您理解。也阅读这篇SO帖子..

让我们考虑您的代码

    int big = 1234567890;     // here your int big=1234567890;
    float approx = big;
    BigDecimal bd=BigDecimal.valueOf(approx);
    System.out.println(bd);  // Now you can see int to float creates approx= 1234567936;
    System.out.println(big - (approx));     // In here big again casting to float since you are doing a operation with float, result is zero.
    System.out.println(big - (int)(approx)); // here big=1234567890 and approx= 1234567936. so difference is -46
于 2013-07-16T04:47:25.873 回答