我知道这有一个简单的答案,但令我感到困惑。
为什么Long.MaxValue可以存储在Double中并以longValue形式返回,但较小的Long会丢失精度。
我原本预计在53位之后会失去精度?这里发生了什么
scala> val x:Double = Long.MaxValue // x: Double = 9.223372036854776E18 (9223372036854775807)
scala> x == Long.MaxValue // Boolean = true
scala> x.longValue == Long.MaxValue // Boolean = true
scala> val y = 1234567890123456789L // y: Long = 1234567890123456789 // less than Long.MaxValue
scala> y < x // Boolean = true
scala> val z:Double = y // z: Double = 1.23456789012345677E18
scala> z == y // Boolean = true
scala> z.longValue == y // Boolean = false // why ? MaxValue fits in the Double
scala> z.longValue // 1234567890123456768 <-- loss of 21
答案 0 :(得分:5)
这不是&#34;拟合&#34;。双打只是inherently inexact。一些值将被准确表示,一些值不会被表示。看起来你找到了一个可以(你的x
)和一个可以(y
)。
您选择的价值观并不特别。这里有类似的行为,其中较小的值明显适合&#34;成双打:
val a = 1.1 // a: Double = 1.1
a == 1.1 // true
val b = 2.2 // b: Double = 2.2
b == 2.2 // true
val c = 1.1 + 2.2 // c: Double = 3.3000000000000003
c == 3.3 // false
答案 1 :(得分:2)
实际上不是拟合,而 会失去精确度。
但是损失是因为它被围捕了:
scala> BigDecimal.exact(Long.MaxValue.toDouble)
res0: scala.math.BigDecimal = 9223372036854775808
scala> Long.MaxValue
res1: Long = 9223372036854775807
当您尝试将过大的Double
放入Long
时会发生什么?
scala> 1e100.toLong
res2: Long = 9223372036854775807
它被截断了。
所以Long.MaxValue
向上舍入为2^63
,可以用53位和二进制指数精确表示,因为它大于Long.MaxValue
,它会变回Long.MaxValue
当你转换为Long
时。