简体   繁体   English

双重到Int没有损失精度

[英]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" 以下声明给出了编译时错误“错误:(19,13)java:不兼容类型:可能从double转换为int的有损转换”

int i1 = 10.0;

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

Question 1 问题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 问题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 如果我显式地将double转换为int然后它编译很好(甚至不是警告),即使我在这个例子中肯定会失去精度

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. 理论上,编译器可以推断#1中的具体示例实际上不会根据文字的值松散精度,但正如您所见 - 它没有。

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. 但是,大多数IDE都可以配置为在这种情况下发出警告。

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. double值赋值给int变量需要缩小转换 ,即使该值是编译时常量,因此需要显式转换。

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. 不同之处在于int (或shortchar )恒定值可以被分配给一个byteshort ,或char可变而不铸造,如果常数实际上在各变量值范围配合,以Java语言规范明确地记载,部分5.2。 Assignment Contexts : 作业上下文

Assignment contexts allow the value of an expression to be assigned ( §15.26 ) to a variable; 赋值上下文允许将表达式的值赋值(第15.26节 )给变量; 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 ) 身份转换( §5.1.1

  • a widening primitive conversion ( §5.1.2 ) 扩展的原始转换(第5.1.2节

  • a widening reference conversion ( §5.1.5 ) 扩大参考转换(第5.1.5节

  • a boxing conversion ( §5.1.7 ) optionally followed by a widening reference conversion 一个拳击转换( §5.1.7 ),可选地后跟一个加宽的引用转换

  • an unboxing conversion ( §5.1.8 ) optionally followed by a widening primitive conversion. 一个拆箱转换(第5.1.8节 ),可选地后跟一个加宽的基元转换。

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. 如果在应用上面列出的转换后,结果类型是原始类型( §4.8 ),则可以应用未经检查的转换(第5.1.9节 )。

In addition, if the expression is a constant expression ( §15.28 ) of type byte , short , char , or int : 此外, 如果表达式是byteshortcharint类型的常量表达式(第15.28节

  • 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 . 如果变量的类型是byteshortchar ,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示

  • 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 . Byte和常量表达式的值可在类型byte表示。

    • Short and the value of the constant expression is representable in the type short . Short和常量表达式的值可以在short类型中表示。

    • Character and the value of the constant expression is representable in the type char . Character和常量表达式的值可在char类型中表示。

Answer to question 1 回答问题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. 根据编译器的精度损失,因为编译器只看到左边有一个int变量,右边有一个double值。 The compiler is not so smart as to figure out that 10.0 will not lose precision when converted to an int. 编译器不是那么聪明,以至于在转换为int时10.0不会失去精度。

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 . 几乎没有人写int x = 10.0

Answer to question 2 回答问题2

Indeed, there is a loss of precision, but why did the compiler not complain? 实际上,精度有所下降,但为什么编译器不抱怨? Because you used a cast. 因为你使用了演员。 You wrote (int) . 你写了(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: 理论上这可能是有可能的, javac在做的时候不会抱怨:

short s = 12;

Even if 12 here is a compile time constant of type int , so it can deduce that no precision is lost. 即使这里的12int类型的编译时常量,也可以推断出没有精度丢失。 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. 好吧当你cast是一个不同的故事时,就像说“相信我,我知道我在做什么”,即使你精确度不高。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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