lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> ----- Original Message -----
> From: Andrew Starks
> To: Lua mailing list
> Sent: Sunday, August 11, 2013 5:19 PM
> Subject: Re: Float numbers equality.
>
>
>
> On Saturday, August 10, 2013, Luiz Henrique de Figueiredo wrote:
>>
>> > Given that this subject comes up every couple of months, and that there
>> > are some subtleties to it, that this warrants a new function in the math
>> > library to do it the right way?
>>
>> I don't think so. Floating-point arithmetic is not simple. I think it'd be
>> a disservice to try to hide its complexities in a official function that
>> may give the impression that it solves the problem reliably, when it
>> can't.
>>
>> On the other hand, there is nothing instrinsically wrong with
>> floating-point
>> equality. The only catches come from numbers that should be equal but are
>> computed in two different ways and from naive expectations such as
>> 300 * 0.7 == 21, due to a misunderstanding that floating-point
>> representation
>> is a binary one, not a decimal one.
>
>
> In an effort to understand (not debate), where would:
>
>        return math.abs(lhs - rhs) < epsilon*rhs
>
> ...be unsuitable? Imagine that I'm dealing with float equality and it isn't
> working. Also imagine that I don't know very much about the issue.  I dig
> into the math library and find a function that does this.
>
> How am I likely to be confused further? What knowledge would I still lack
> that would keep me from understanding, provided that PiL offered some
> additional context?
>
> As a post script, I took the advice found in Programming In Lua[1] and found
> myself utterly lost (although ever so slightly closer to my Calculus Through
> Googling degree). I read the part of the discussion related to the epsilon,
> but since so much of it was aimed at an audience that wasn't me, I failed to
> identify the solution.
>
> As a result, I believe that once I feel like I understand the common issues,
> I should (or someone like me should) write a wiki on it. I was unable to
> find a really good document aimed at someone who can't read calculus
> notation. Several Microsoft articles came very close, however.
>
> - Andrew
> [1] http://www.fer.unizg.hr/_download/repository/paper%5B1%5D.pdf

On Sun, Aug 11, 2013 at 9:03 AM, Victor Bombi <sonoro@telefonica.net> wrote:
> In case rhs < 0

For the sake of having an actually productive discussion, let's assume
he ACTUALLY meant the bugfixed version:

return math.abs(lhs - rhs) < math.abs(epsilon * rhs)

The expression itself is never really WRONG (if you're paranoid you
might replace the < with a <= to handle underflow in the epsilon*rhs
term, but more on this later), but there are cases when direct
floating-point equality works just fine and the expression is a
comparatively-expensive waste of time.

The real problem is in understanding what a suitable epsilon really is
and how to minimize the error in the calculation. This requires an
understanding of your specific problem domain and gets into analysis
of the behavior of rounding error of floating-point operations. A
*single* addition/subtraction won't introduce relative error greater
than IIRC 2^-52 (maybe 2^-51? I forget exactly), while a
multiplication or division can introduce more, and more complicated
expressions like logarithm or square root could really throw the whole
thing off if you do it wrong.

Long story short, this expression is often the right thing to do, but
it's meaningless to do it if your calculation leading into it triggers
nasty rounding errors. Proper understanding of how to rearrange a FP
calculation to minimize error is far more important than the actual
epsilon comparison.

/s/ Adam