-
Notifications
You must be signed in to change notification settings - Fork 14
Description
Describe the bug
The test for aboutEqual doesn't pass, plus it makes some floats equal whereas there are clearly not.
To Reproduce
Running 1 test. To reproduce these results, run: elm-test --fuzz 10000 --seed 225971905022788
↓ FloatTests
✗ makes numbers about equal even after some operations
Given 8.98846567431158e+307
False
╷
│ Expect.equal
╵
True
in the repl:
> (1.00002 + 1.00002) |> Float.Extra.aboutEqual 2.00003
True : Bool
Expected behavior
I'm not sure about what should be the "good behavior". The fuzz test shows that aboutEqual is "too strict", whereas the 1.00002 + 1.00002 is "too loose".
Maybe we should provide multiple functions aboutEqual function like aboutEqualReallyStrict/aboutEqualStrict/aboutEqualLoose/aboutEqualReallyLoose, or adding an integer parameter indicating the "strictness" of this function.
Maybe it's even not a core lib's library to make such choices, so we shouldn't provide this function at all.
Additional context
We could consider the following implementation : https://github.com/sindresorhus/float-equal/blob/main/index.js
Translated in elm with the "strictness" parameter (which we can be the number of significant bits, with 52 as the maximum precision):
{-| Corresponds to Number.EPSILON.
See: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON>
-}
epsilon : Float
epsilon =
2 ^ -52
aboutEqual : { significantBits : Int } -> Float -> Float -> Bool
aboutEqual { significantBits } a b =
if isInfinite a then
isInfinite b
else if isInfinite b then
False
else
let
diff =
abs (a - b)
in
(diff < epsilon)
|| (diff <= (2.0 ^ toFloat (52 - significantBits)) * epsilon * min (abs a) (abs b))