以下代码的输出是
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?
答案 0 :(得分:4)
第一个输出是0.0,因为来自int的float子句使得整个语句变为float。
这意味着int big也转换为浮点值。基本上你做的是(约 - )(float)big = approx.
这应该是你获得零的原因。
如果你想尝试这个也
System.out.println(big/(approx));
int
和float
之间的操作会将整个语句转换为float
答案 1 :(得分:3)
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
中,由于approx
是float
,因此将其视为浮点运算。 big
被扩展为float
,由于approx
也big
扩展为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