[英]Double to Int without lossy precision
以下声明给出了编译时错误“错误:(19,13)java:不兼容类型:可能从double转换为int的有损转换”
int i1 = 10.0;
// Error:(19, 14) java: incompatible types: possible lossy conversion from double to int
问题1
我理解错误,但编译器可以不推断 - 在这种特殊情况下 - 不会有精度损失?
问题2
如果我显式地将double转换为int
然后它编译很好(甚至不是警告),即使我在这个例子中肯定会失去精度
int i2 = (int)9999999999999.999999999;
如果我无法编译第一种情况 - 没有发生丢失 - 那么为什么第二个显式转换示例甚至不会生成编译器警告?
理论上,编译器可以推断#1中的具体示例实际上不会根据文字的值松散精度,但正如您所见 - 它没有。
显式转换信号通知编译器您知道处理它的情况,因此代码实际编译。 但是,大多数IDE都可以配置为在这种情况下发出警告。
将double
值赋值给int
变量需要缩小转换 ,即使该值是编译时常量,因此需要显式转换。
不同之处在于int
(或short
或char
)恒定值可以被分配给一个byte
, short
,或char
可变而不铸造,如果常数实际上在各变量值范围配合,以Java语言规范明确地记载,部分5.2。 作业上下文 :
赋值上下文允许将表达式的值赋值(第15.26节 )给变量; 必须将表达式的类型转换为变量的类型。
赋值上下文允许使用以下之一:
身份转换( §5.1.1 )
扩展的原始转换(第5.1.2节 )
扩大参考转换(第5.1.5节 )
一个拳击转换( §5.1.7 ),可选地后跟一个加宽的引用转换
一个拆箱转换(第5.1.8节 ),可选地后跟一个加宽的基元转换。
如果在应用上面列出的转换后,结果类型是原始类型( §4.8 ),则可以应用未经检查的转换(第5.1.9节 )。
此外, 如果表达式是
byte
,short
,char
或int
类型的常量表达式(第15.28节 ) :
如果变量的类型是
byte
,short
或char
,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示 。如果变量的类型是:则可以使用缩小的基元转换,然后进行装箱转换:
Byte
和常量表达式的值可在类型byte
表示。
Short
和常量表达式的值可以在short
类型中表示。
Character
和常量表达式的值可在char
类型中表示。
回答问题1
根据编译器的精度损失,因为编译器只看到左边有一个int变量,右边有一个double值。 编译器不是那么聪明,以至于在转换为int时10.0
不会失去精度。
理论上可以构建编译器以允许编译该语句,但这样做没有实际好处。 几乎没有人写int x = 10.0
。
回答问题2
实际上,精度有所下降,但为什么编译器不抱怨? 因为你使用了演员。 你写了(int)
。 这是您向编译器显示您知道自己在做什么。 通过编写演员表,你告诉它你知道可能会失去精确度。
有趣的问题
理论上这可能是有可能的, javac
在做的时候不会抱怨:
short s = 12;
即使这里的12
是int
类型的编译时常量,也可以推断出没有精度丢失。 我想这是编译器团队认为最合适的。
好吧当你cast
是一个不同的故事时,就像说“相信我,我知道我在做什么”,即使你精确度不高。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.