Skip to content

Float.Extra.aboutEqual weirdnesses #41

@sebsheep

Description

@sebsheep

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))

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions