在扩大转换期间失去精确度

时间:2013-07-16 04:24:38

标签: java types type-conversion

以下代码的输出是

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

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

4 个答案:

答案 0 :(得分:4)

第一个输出是0.0,因为来自int的float子句使得整个语句变为float。

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

如果你想尝试这个也

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

intfloat之间的操作会将整个语句转换为float

答案 1 :(得分:3)

Java中的

float使用23位尾数加1个implisit位,因此有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
}

答案 2 :(得分:3)

这由JLS §4.2.4涵盖:

  

如果二元运算符的至少一个操作数是   浮点类型,那么操作是浮点运算,   即使另一个是不可或缺的。

在您的第一个示例big - approx中,由于approxfloat,因此将其视为浮点运算。 big被扩展为float,由于approxbig扩展为float,因此精度损失会自行取消,从而为您提供答案为零。

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

答案 3 :(得分:1)

阅读this可能会帮助您理解。阅读this 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