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