Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to test equality of floating point numbers #83

Open
jewiet opened this issue Apr 23, 2019 · 7 comments
Open

Impossible to test equality of floating point numbers #83

jewiet opened this issue Apr 23, 2019 · 7 comments

Comments

@jewiet
Copy link

jewiet commented Apr 23, 2019

Hey!

Thanks for the tool.

I want to use elm-verify-examples to test a function that returns a float. It seems impossible to test equality of floating point numbers, even if they are strictly equal. Consider the following example:

0.1 --> 0.1

With this I am getting the following message: Do not use Expect.equal with floats. Use Float.within instead.

@gampleman
Copy link
Collaborator

Generally speaking I think if you are going to be using floating point numbers in examples, then they should be very close matches indeed. As such, if we knew what was a floating point test, we could pick some fairly reasonable values for the Expect.within call (and perhaps those could even be configurable in elm-verify-examples.json).

However, the main issue is working out when to use floating point comparison. I think there are a few options, but they all have downsides:

  1. We attempt to detect floating point numbers by syntax. This would mean that if you write --> 3.0 this would work, however, if you wrote --> 2/5 this would not. 😒
  2. We introduce special syntax for this --~ (say). 😒
  3. We politely ask elm-test maintainers (@Janiczek) to perhaps revert this decision and allow exact equality for floats. Personally I think the current solution is a bit ham-fisted and perhaps a future api more like Better expect API elm-explorations/test#216 would be a better solution to the problem elm-test is trying to solve - as direct floating point equality is prohibited and good alternative exists, but floating points contained in data structures have no real solution in elm-test.

@ianmackenzie
Copy link
Contributor

For what it's worth I don't think option 1 is so bad...are there actually many cases where you might want to write a fraction?

One nice thing about option 1 is that then you don't have to worry about having an arbitrary tolerance, you can instead check whether the actual numeric result formatted to the same number of decimal places used in the example result gives the same string as the example result. Literally test that if you ran the example code and printed out the result to the same number of decimal places, would you get the same output...

I guess you could argue that that that could be affected by rounding settings, but you could accomplish pretty much the same thing by using a tolerance set to 10^-n where n is the number of decimal digits shown in the example result. (e.g. if an example shows an output of 2.34, then that should definitely be accurate to within 0.01...)

@gampleman
Copy link
Collaborator

I think 1. is bad mostly for the unintuitive behaviour:

  • 1 would behave differently from 1.0. This is not the same as how elm behaves.
  • foo bar --> sin bar or some such may be a perfectly sensible way to describe the result (remember the goal here is to communicate)

Deriving the precision from the number of decimal digits is a good idea though!

My preferred option would be 3, but failing that 1 is probably the best way forward.

@ianmackenzie
Copy link
Contributor

Option 3 is pretty annoying if you have examples where the result is (unavoidably) irrational though...if you wanted to write out an example for a circle area or sphere volume function you'd need to include all 17 decimal places or whatever if you wanted the parsed number to be exactly equal to the actual result. Even something like (famously)

0.1 + 0.2 --> 0.3

doesn't work, you'd have to write

0.1 + 0.2 --> 0.30000000000000004

which seems...not ideal.

@ianmackenzie
Copy link
Contributor

The foo bar --> sin bar thing is hard to figure out how to deal with though...I think the only not-overly-magical solution there is to just specify a floating point tolerance in elm-verify-examples.json.

@stoeffel
Copy link
Owner

stoeffel commented Oct 25, 2023

We could also specify the precision per example, something like

-- Precision: 1
0.1 + 0.2 --> 0.3

@gampleman
Copy link
Collaborator

The problem isn't (only) specifying the tolerance there, but even knowing that you should be using floating point equality.

0.1 + 0.2 --> 0.30000000000000004

I personally think that's fine, since at least its accurate. Like if someone copies 0.1 + 0.2 into elm repl, they will get exactly what it says in the docs. Now you as a documentation writer might not like having to specify so many decimal digits, but perhaps you could just pick a nicer example?

ianmackenzie added a commit to generative-engineering/core-extra that referenced this issue Mar 26, 2024
Work around current limitations in elm-verify-examples (see stoeffel/elm-verify-examples#83)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants