我正在使用Scala AnyVal
类型并且无法解读以下内容:我将Long.MaxValue
转换为Double
并返回Long
。由于Long
(64位)可以保存比Double
尾数(52位)更多的数字,我预计此转换会使某些数据丢失,但不是这样的情况:
Long.MaxValue.equals(Long.MaxValue.toDouble.toLong) // is true
我认为Long.MaxValue.toDouble.toLong
中可能存在一些魔法/优化,以至于转换并非真正发生。所以我也试过了:
Long.MaxValue.equals("9.223372036854776E18".toDouble.toLong) // is true
如果我评估表达式"9.223372036854776E18".toDouble.toLong
,则会给出:
9223372036854775807
这真让我烦恼,最后4位数似乎只是突然冒出来了!
答案 0 :(得分:3)
首先:像往常一样有这样的问题,Scala没有什么特别之处,所有现代语言(我所知道)都使用IEEE 754浮点(至少在实践中,如果语言规范不是这样的话)需要它)并且行为相同,只是使用不同的类型和操作名称。
是的,数据丢失了。如果您尝试例如(Long.MaxValue - 1).toDouble.toLong
,您仍会获得Long.MaxValue
。您可以在Long
找到下一个最小的someDouble.toLong
,如下所示:
scala> Math.nextDown(Long.MaxValue.toDouble).toLong
res0: Long = 9223372036854774784
如果我评估表达式
"9.223372036854776E18".toDouble.toLong
,则会给出:9223372036854775808
这真让我烦恼,最后4位数似乎只是突然冒出来了!
你可能意味着9223372036854775807
。 9.223372036854776E18
当然实际上大于它:它代表9223372036854776000
。但是,如果您使用大于Double
的任何其他Long.MaxValue
,您将获得相同的结果,例如1E30.toLong
。
答案 1 :(得分:0)
请注意,Scala中的Double和Long值相当于double和long的原始类型。
Long.MaxValue.toDouble
的结果实际上比Long.MaxValue
更大,原因是,该值是四舍五入的。下一次转换,即Long.MaxValue.toDouble.toLong
是"舍入"回到Long.MaxValue
。