不同的行为可能会导致精度下降 [英] Varying behavior for possible loss of precision
问题描述
在Java中,当你这样做时
In Java, when you do
int b = 0;
b = b + 1.0;
您可能会丢失精度错误。但是为什么如果你这样做
You get a possible loss of precision error. But why is it that if you do
int b = 0;
b += 1.0;
没有任何错误?
推荐答案
那是因为 b + = 1.0;
相当于 b =(int)((b)+ (1.0));
。 缩小基元转换(JLS) 5.1.3)隐藏在复合赋值操作中。
That's because b += 1.0;
is equivalent to b = (int) ((b) + (1.0));
. The narrowing primitive conversion (JLS 5.1.3) is hidden in the compound assignment operation.
E1 op = E2 形式的复合赋值表达式等效于 E1 =(T)((E1)op(E2 )),其中 T 是 E1 的类型,但 E1 仅评估一次。
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:
short x = 3;
x += 4.6;
并导致 x
的值为 7
因为它相当于:
and results in x
having the value 7
because it is equivalent to:
short x = 3;
x = (short)(x + 4.6);
这也解释了为什么以下代码编译:
This also explains why the following code compiles:
byte b = 1;
int x = 5;
b += x; // compiles fine!
但这不是:
byte b = 1;
int x = 5;
b = b + x; // DOESN'T COMPILE!
在这种情况下你需要明确投出:
You need to explicitly cast in this case:
byte b = 1;
int x = 5;
b = (byte) (b + x); // now it compiles fine!
值得注意的是复合赋值中的隐式转换是精彩的书籍 Java Puzzlers 的 Puzzle 9:Tweedledum 的主题> 。以下是本书的一些摘录(为了简洁而略微编辑):
It's worth noting that the implicit cast in compound assignments is the subject of Puzzle 9: Tweedledum from the wonderful book Java Puzzlers. Here are some excerpt from the book (slightly edited for brevity):
许多程序员认为
x + = i ;
只是x = x + i;
的简写。这不完全正确:如果结果的类型比变量的类型宽,则复合赋值运算符执行静默缩小基元转换。
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.
避免不愉快惊喜,不要对类型为 byte
, short
的变量使用复合赋值运算符,或者炭
。在类型 int
的变量上使用复合赋值运算符时,请确保右侧的表达式不是 long $ c $类型c>,
float
,或 double
。在类型为 float
的变量上使用复合赋值运算符时,请确保右侧的表达式不是 double $ c $类型C>。这些规则足以阻止编译器生成危险的缩小强制转换。
To avoid unpleasant surprises, do not use compound assignment operators on variables of type byte
, short
, or char
. When using compound assignment operators on variables of type int
, ensure that the expression on the right-hand side is not of type long
, float
, or double
. When using compound assignment operators on variables of type float
, ensure that the expression on the right-hand side is not of type double
. 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复合赋值)。
The last paragraph is worth noting: C# is a lot more strict in this regard (see C# Language Specification 7.13.2 Compound assignment).
这篇关于不同的行为可能会导致精度下降的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!