lua-users home
lua-l archive

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


On 8/18/13, Coda Highland <chighland@gmail.com> wrote:
> On Sun, Aug 18, 2013 at 4:33 PM, Leo Razoumov <slonik.az@gmail.com> wrote:
>> On 8/18/13, Coda Highland <chighland@gmail.com> wrote:
>>> On Sun, Aug 18, 2013 at 4:09 PM, Leo Razoumov <slonik.az@gmail.com>
>>> wrote:
>>>> On 8/9/13, Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> wrote:
>>>>>> function float_equal(lhs, rhs, epsilon)
>>>>>>     return math.abs(lhs - rhs) < epsilon
>>>>>> end
>>>>>
>>>>> As mentioned before, if you have to do this, you need to use
>>>>> *relative*
>>>>> error,
>>>>> not absolute error:
>>>>>       return math.abs(lhs - rhs) < epsilon*rhs
>>>>>
>>>>
>>>> The code above is incorrect for rhs <= 0.
>>>>
>>>> It is better to try the following (untested):
>>>>
>>>> function float_equal(lhs, rhs, epsilon)
>>>>     local abs= math.abs
>>>>     epsilon  = epsilon or 1E-12
>>>>     return abs(lhs - rhs) <= epsilon * (abs(lhs) + abs(rhs))
>>>> end
>>>>
>>>> This implementation handles correctly the cases when one or both
>>>> numbers are zero or negative,
>>>>  and, (the added bonus) the function is symmetrical w.r.t. lhs<->rhs
>>>> substitutions.
>>>>
>>>> --Leo--
>>>>
>>>
>>> Actually, the correction is simply to use "epsilon * abs(rhs)" instead
>>> of "epsilon * rhs".
>>>
>>
>> No, expression
>>     return abs(lhs - rhs) <= epsilon * abs(rhs)
>> does not handle the case of rhs=0.
>> E.g.: epsilon=1E-12; lhs= 1E-16; rhs=0;
>>
>> --Leo--
>>
>
> Hmm. That's a good point on the degenerate case, but at THAT point I
> would use an if statement for rhs == 0.0 rather than trying to bake it
> into the expression -- perhaps "if rhs == 0.0 then return abs(lhs) <=
> epsilon end".
>
> /s/ Adam
>

Adam,
in general one expects the equality operation to be symmetrical so that
float_equal(x,y) and float_equal(y,x) return the same result.
I think the simplest form that satisfies symmetry requirement and which does
not require any special case handling is

    return abs(lhs - rhs) <= epsilon * (abs(lhs) + abs(rhs))

--Leo--