Scala中的数字扩展令人惊讶

时间:2019-05-13 02:33:04

标签: scala

代码

object Test {
        def main(args: Array[String]): Unit = {
                val x = 123456789L
                val y = 1.0F

                val a = x - (if (true) { x } else { y })
                val b = (if (true) { x } else { y }) - x
        }
}

结果

运行此代码,a为-3.0: Float,b为0.0: Float。 (由于精度损失,x.toFloat1.23456792E8: Float。)


Scala规范

根据Conditional ExpressionsWeak Conformance:在两种情况下,if表达式的类型均为Float。 ({FloatLong(那么部分的类型)和Float(其他部分的类型)的最小最小上限。

结果,在第一种情况下,我们有Long - Float,在第二种情况下,我们有Float - Long

在第一种情况下,两个操作数都被加宽(?)到Double以进行计算,结果被缩小到Float以进行赋值。在第二种情况下,两个操作数都仅扩展为Float

根据Numeric Wideninga的预期类型必须为Double,两个操作数才能扩展为Double。但是,它是Float

这是怎么回事?这里还有其他规则吗?这是编译器中的错误吗?请详细解释并引用支持证据。谢谢。


字节码

可以通过查看生成的字节码来确认观察到的行为:

$ javap -c 'Test$.class'
Compiled from "Test.sc"
public final class Test$ {
  public static final Test$ MODULE$;

  public static {};
    Code:
       0: new           #2                  // class Test$
       3: invokespecial #12                 // Method "<init>":()V
       6: return

  public void main(java.lang.String[]);
    Code:
       0: ldc2_w        #15                 // long 123456789l
       3: lstore_2
       4: fconst_1
       5: fstore        4
       7: lload_2
       8: l2d
       9: lload_2
      10: l2f
      11: f2d
      12: dsub
      13: d2f
      14: fstore        5
      16: lload_2
      17: l2f
      18: lload_2
      19: l2f
      20: fsub
      21: fstore        6
      23: return
}

对比度:

  1. l2d,后一种情况是l2ff2d;和第二种情况下的l2f
  2. dsub,后一种情况是d2f;和第二种情况下的fsub

信用

https://twitter.com/aphyr/status/831200481141805056

0 个答案:

没有答案