双精度至整数,无损失精度

时间:2018-09-09 16:36:41

标签: java casting compiler-errors

以下声明给了我一个编译时错误“错误:(19,13)java:不兼容的类型:可能从双精度转换为整数”

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;

如果我不能编译第一种情况-没有损失-那么为什么第二个带有显式转换的示例甚至没有生成编译器警告?

4 个答案:

答案 0 :(得分:2)

理论上,编译器可以推断出#1中的特定示例实际上不会基于文字的值来降低精度,但是正如您所看到的那样-不会。

显式强制转换向编译器发出信号,告知您已知道要处理的情况,因此代码实际进行了编译。但是,大多数IDE也可以配置为在这种情况下发出警告。

答案 1 :(得分:2)

double值分配给int变量将需要narrowing conversion,即使该值是编译时常量,因此需要明确的演员表。

除了可以将int(或shortchar)常数值分配给byteshort ,或char变量,如果常量确实符合变量值范围(如Java语言规范第5.2. Assignment Contexts节中明确记录的内容),则该变量不进行强制转换:

  

分配上下文允许将表达式的值分配(§15.26)到变量;表达式的类型必须转换为变量的类型。

     

分配上下文允许使用以下之一:

     
      
  • 身份转换(§5.1.1

  •   
  • 不断扩大的原始转换(§5.1.2

  •   
  • 扩展参考转换(§5.1.5

  •   
  • 装箱转换(§5.1.7)之后可以选择加宽引用转换

  •   
  • 取消装箱转换(§5.1.8),然后可以选择扩展原始转换。

  •   
     

如果在应用了上面列出的转换后,结果类型为原始类型(§4.8),则可以应用未经检查的转换(§5.1.9)。

     

此外,如果表达式是类型为byteshortcharint的常量表达式(§15.28)< / strong>:

     
      
  • 如果变量的类型为byteshortchar,并且常量表达式的值为:可表示为变量的类型

  •   
  • 如果变量的类型为:

    ,可以使用变窄的原始转换,然后是装箱转换。

         
        
    • Byte,常量表达式的值可以用byte类型表示。

    •   
    • Short,常量表达式的值可以用short类型表示。

    •   
    • Character,常量表达式的值可以用char类型表示。

    •   
  •   

答案 2 :(得分:1)

问题1的答案

根据编译器,精度会下降,因为编译器只会看到您在左侧有一个int变量,在右侧有一个double值。编译器并不聪明,以至于10.0转换为int时不会失去精度。

理论上可以构建编译器以允许该语句进行编译,但是这样做并没有真正的好处。几乎没有人写int x = 10.0

问题2的答案

的确确实存在精度损失,但是为什么编译器没有抱怨?因为您使用了演员表。您写了(int)。这是向编译器表明您知道自己在做什么。通过编写演员表,您告诉它您知道可能会失去精度。

答案 3 :(得分:1)

有趣的问题

从理论上讲这是可能的,project_id这样做时不会抱怨:

javac

即使short s = 12; 12类型的编译时间常数,也可以推断出没有精度损失。我猜这是编译器团队认为最合适的。

好吧,当您int是一个不同的故事时,即使您放宽了精度,这就像说“相信我,我知道我在做什么”。