Varying behavior for possible loss of precision
当你在JavaP></
1 2 | int b = 0; b = b + 1.0; |
你得到的可能损失的精度误差。为什么是它,但如果你给P></
1 2 | int b = 0; b += 1.0; |
不有任何错误吗?P></
这是因为
A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.
For example, the following code is correct:
1
2 short x = 3;
x += 4.6;and results in
x having the value7 because it is equivalent to:
1
2 short x = 3;
x = (short)(x + 4.6);
这也解释了以下代码编译的原因:
1 2 3 | byte b = 1; int x = 5; b += x; // compiles fine! |
但这并不是:
1 2 3 | byte b = 1; int x = 5; b = b + x; // DOESN'T COMPILE! |
在这种情况下,需要显式强制转换:
1 2 3 | byte b = 1; int x = 5; b = (byte) (b + x); // now it compiles fine! |
值得注意的是,隐含的复合式赋值是谜题9的主题:ToeDeDelm从奇妙的书Java拼图。以下是这本书的一些摘录(为简洁起见稍作编辑):
Many programmers think that
x += i; is simply a shorthand forx = x + i; . This isn't quite true: if the type of the result is wider than that of the variable, the compound assignment operator performs a silent narrowing primitive conversion.To avoid unpleasant surprises, do not use compound assignment operators on variables of type
byte ,short , orchar . When using compound assignment operators on variables of typeint , ensure that the expression on the right-hand side is not of typelong ,float , ordouble . When using compound assignment operators on variables of typefloat , ensure that the expression on the right-hand side is not of typedouble . These rules are sufficient to prevent the compiler from generating dangerous narrowing casts.For language designers, it is probably a mistake for compound assignment operators to generate invisible casts; compound assignments where the variable has a narrower type than the result of the computation should probably be illegal.
最后一段值得注意:C在这方面更严格(见C语言规范7.13.2复合赋值)。