[英]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
(或short
或char
)恒定值可以被分配给一个byte
, short
,或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:
赋值上下文允许使用以下之一:
a widening primitive conversion ( §5.1.2 )
扩展的原始转换(第5.1.2节 )
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
, orint
:此外, 如果表达式是
byte
,short
,char
或int
类型的常量表达式(第15.28节 ) :
A narrowing primitive conversion may be used if the type of the variable is
byte
,short
, orchar
, and the value of the constant expression is representable in the type of the variable .如果变量的类型是
byte
,short
或char
,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示 。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 typebyte
.Byte
和常量表达式的值可在类型byte
表示。
Short
and the value of the constant expression is representable in the typeshort
.Short
和常量表达式的值可以在short
类型中表示。
Character
and the value of the constant expression is representable in the typechar
.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. 即使这里的
12
是int
类型的编译时常量,也可以推断出没有精度丢失。 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.