Closed michaelmior closed 11 months ago
That number cannot be represented exactly in a Double
, so the behavior is correct.
Example:
scala> 738270448276026960L
res0: Long = 738270448276026960
scala> res0.toDouble
res1: Double = 7.3827044827602701E17
scala> res1.toLong
res2: Long = 738270448276027008
A BigInt
is a Double
if the represented values are identical, not if a lossy conversion one way or the other results in the same thing.
For instance. 2.3
converts to 2
, but 2.3
is not a BigInt
value.
That ==
uses Double
equality for Long
values that cannot be precisely represented as a Double
is a questionable choice, because it breaks the contract for hashCode
(that if a==b
then a.## == b.##
). But it's not an issue with BigInt
; BigInt
correctly says it's not the same as the Double
representation.
scala> BigInt(res0)
res3: scala.math.BigInt = 738270448276026960
scala> res3 == res1
res4: Boolean = false
scala> res0 == res1 // Um...really?
res5: Boolean = true
Apologies as I didn't notice that it clearly isn't the same number. I suppose this can be closed.
As a refresher, the spec phrase for the promotion to double is "operation type". (https://scala-lang.org/files/archive/spec/2.13/12-the-scala-standard-library.html#numeric-value-types)
I don't know why it's not called "uncooperative equality".
The change a few years to warn about lossy conversions includes a smarter comment to the effect that once floating point is involved, your spidey sense must kick in to save you from incorrect assumptions about how an integral type will behave.
This is a good opportunity to show appreciation for the brave people who work with numbers. We thank you for your service.
Reproduction steps
Scala version: 2.13.11
Problem
I would expect that since calling
toDouble
converts to the exact sameDouble
value, thatisValidDouble
would return true.