Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
147 views
in Technique[技术] by (71.8m points)

java - Varying behavior for possible loss of precision

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;

There isn't any error?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

JLS 15.26.2 Compound Assignment Operators (JLS Third Edition):

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;

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!

But this doesn't:

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!

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):

Many programmers think that x += i; is simply a shorthand for x = 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, 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.

The last paragraph is worth noting: C# is a lot more strict in this regard (see C# Language Specification 7.13.2 Compound assignment).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...