简体   繁体   中英

Double to Int without lossy precision

The following declaration gives me a compile-time error "Error:(19, 13) java: incompatible types: possible lossy conversion from double to int"

int i1 = 10.0;

// Error:(19, 14) java: incompatible types: possible lossy conversion from double to int

Question 1

I understand the error but can the compiler not infer - in this particular case - that there will be no loss of precision?

Question 2

If I explicitly convert the double to an int then it compiles fine (not even a warning) even though I am definitely losing precision in this example

int i2 = (int)9999999999999.999999999;

If I can't compile the first case - where no loss occurs - then why does this second example with the explicit conversion not even generate a compiler warning?

In theory, a compiler could infer that the specific example in #1 wouldn't actually loose precision based on the literal's value, but as you've seen - it doesn't.

The explicit cast signals to the compiler that you are aware of the situation an handling it, so the code actually compiles. Most IDEs, however, could be configured to emit a warning in such a situation too.

The assignment of a double value to an int variable would require a narrowing conversion , even if the value is a compile-time constant, and hence requires an explicit cast.

Except that an int (or short or char ) constant value can be assigned to a byte , short , or char variable without casting, if the constant actually fits in the variables value range, as explicitly documented in the Java Language Specification, section 5.2. Assignment Contexts :

Assignment contexts allow the value of an expression to be assigned ( §15.26 ) to a variable; the type of the expression must be converted to the type of the variable.

Assignment contexts allow the use of one of the following:

  • an identity conversion ( §5.1.1 )

  • a widening primitive conversion ( §5.1.2 )

  • a widening reference conversion ( §5.1.5 )

  • a boxing conversion ( §5.1.7 ) optionally followed by a widening reference conversion

  • an unboxing conversion ( §5.1.8 ) optionally followed by a widening primitive conversion.

If, after the conversions listed above have been applied, the resulting type is a raw type ( §4.8 ), an unchecked conversion ( §5.1.9 ) may then be applied.

In addition, if the expression is a constant expression ( §15.28 ) of type byte , short , char , or int :

  • A narrowing primitive conversion may be used if the type of the variable is byte , short , or char , and the value of the constant expression is representable in the type of the variable .

  • A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is:

    • Byte and the value of the constant expression is representable in the type byte .

    • Short and the value of the constant expression is representable in the type short .

    • Character and the value of the constant expression is representable in the type char .

Answer to question 1

There is a loss of precision according to the compiler, because the compiler only sees that you have an int variable on the left and a double value on the right. The compiler is not so smart as to figure out that 10.0 will not lose precision when converted to an int.

The compiler could in theory be built to allow that statement to compile, but there is no real benefit in doing so. Almost no one writes int x = 10.0 .

Answer to question 2

Indeed, there is a loss of precision, but why did the compiler not complain? Because you used a cast. You wrote (int) . This is you showing the compiler that you know what you're doing. By writing a cast, you are telling it that you are aware that there is a possible loss of precision.

Interesting question

In theory this could be possible, well javac does not complain when doing:

short s = 12;

Even if 12 here is a compile time constant of type int , so it can deduce that no precision is lost. I guess this is what the compiler team thought would be most appropriate.

Well when you cast is a different story, it's like saying "trust me, I know what I'm doing", even if you loose precision.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM