# [R] Creating logical value from the difference of two absolute values

Martin Maechler maechler at stat.math.ethz.ch
Sat Nov 20 21:07:43 CET 2004

```>>>>> "DougB" == Douglas Bates <bates at stat.wisc.edu>
>>>>>     on Fri, 19 Nov 2004 06:59:49 -0600 writes:

DougB> Nathan Leon Pace, MD, MStat wrote:
>> Hi,
>>
>> Using R 2.0.1 on Mac g5 running Mac OS X 10.3.6.
>>
>> I would expect that
>>
>> abs(.7 - .5) >= abs(.3 - .5) should be returned TRUE.
>>
>>
>> > www <- abs(.7 - .5) >= abs(.3 - .5)
>> > www
>> [1] FALSE
>>
>> Is this a result of floating point or the implementation of abs or
>> something else?

DougB> Due to floating point arithmetic in general, not specifically the abs
DougB> function.  The number .5 will have an exact floating point
DougB> representation but .3 and .7 will not.  Making equality comparisons with
DougB> floating point values is always risky.

>> In a function I need to compare two absolute values - each being of the
>> form |variable - constant|.

DougB> On a Mac I get

>> abs(.7-.5) - abs(.3-.5)
DougB> [1] -5.551115e-17

DougB> so you need to make a relative comparison, not an absolute comparison.
DougB> You could write the relative comparison using the all.equal function,

yes,

DougB> such as

>> v1 <- abs(.7-.5)
>> v2 <- abs(.3-.5)
>> (v1 > v2) || all.equal(v1, v2)

DougB> [1] TRUE

but unfortunately,  in such situations,  all.equal() has to be
used more cautiously :

>  v1 <- 1; v2 <- 10
>  (v1 > v2) || all.equal(v1, v2)
Error in (v1 > v2) || all.equal(v1, v2) : invalid `y' type in `x || y'

since it doesn't return 'FALSE' but a string in the non-TRUE case.
One "correct" way (*) to use it is

(v1 > v2) || identical(TRUE, all.equal(v1, v2))

I've asked myself quite a few times in the past if it wasn't worth
defining an   is.all.equal(.)
function  that would really do what one might (and you implicitly
did) expect of all.equal(.).

Maybe we really should provide it, just for the sake of code
clarity {and teaching "how to"s}.

Martin

(*) a shorter but much less readable version is
(v1 > v2) || is.logical(all.equal(v1, v2))

```