[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Float numbers equality.
- From: Coda Highland <chighland@...>
- Date: Sun, 18 Aug 2013 18:46:31 -0700
On Sun, Aug 18, 2013 at 5:16 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: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--
>
As I said, this causes a misinterpretation of epsilon by an order of
magnitude. If you wish to avoid special case code (which makes the
function much more readable and probably runs faster), then you must
use something like epsilon * max(abs(lhs), abs(rhs)).
/s/ Adam