[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Float numbers equality.
- From: Leo Razoumov <slonik.az@...>
- Date: Sun, 18 Aug 2013 20:16:35 -0400
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--