为什么java +=
得到错误的结果,我该如何防止这个问题? (例如在IDE中以任何方式显示warning
?)
我试过eclipse& IntelliJ但都没有显示任何警告。
示例代码:
{
long a = 20000000000000000L;
double b = 90.0;
a += b;
System.out.println(a); // 20000000000000088 NG
}
{
long a = 10000000000000000L;
double b = 90.0;
a += b;
System.out.println(a); // 10000000000000090 OK
}
{
long a = 20000000000000000L;
double b = 90.0;
a += (long) b;
System.out.println(a); // 20000000000000090 OK
}
答案 0 :(得分:10)
根据JLS,compound assignment expression
a += b;
相当于
a = (long) (a + b);
由于b
是double
,binary numeric promotion会在添加发生之前发生。两个操作数都转换为double
值,并且使用浮点运算进行加法。
值20000000000000090
无法完全表示为double
,因此您会失去精确度,而是获得20000000000000088
。然后它会被转换回long
,它具有足够的精度来表示20000000000000088
。
您的第二个代码段生成10000000000000090
,可以完全表示为double
。
您的第三个代码段相当于
a = (long) (a + (long) b);
使用integer arithmetic。 20000000000000090
可以表示为long
。
我不知道有任何工具可以警告你。
相关:
答案 1 :(得分:1)
Java使用64-bit IEEE floating point numbers,它使用53个二进制数字来表示重要数字。在第一个例子中,
import pymongo
db_connect = pymongo.MongoClient('192.168.4.202', 20020)
database_name = 'MY_DATABASE_NAME'
database = db_connect[database_name]
collection = database.collection_names(include_system_collections=False)
for collect in collection:
print collect
此处变量{
long a = 20000000000000000L;
double b = 90.0;
a += b;
System.out.println(a); // 20000000000000088 NG
}
将转换为必须使用大于1的指数来表示它的double,并且它将不再是值20000000000000000L的精确表示。
在此示例中,可以仅使用有效数和指数为1来表示a
。
a
在此示例中,{
long a = 10000000000000000L;
double b = 90.0;
a += b;
System.out.println(a); // 10000000000000090 OK
}
显式转换为long,从而无需将b
转换为double并执行浮点运算。
a
答案 2 :(得分:0)
并非所有程序员(像我一样)都能理解binary numeric promotion,
为防止此类COMPGED
编码丢失,我找到了一种简单的方法:只禁止所有+=
作为编码规则。
我只是在我的项目中点击所有+=
,然后将+=
更改为a += b
。
IDE在a = a + b
操作时类型不匹配时显示错误,如下所示: