thothal
thothal

Reputation: 20409

Compare floats in R

Disclaimer

I was not sure whether to post that here or on CV but after having read what is on topic on CV I think it is more R specific then purely statistical. Thus, I posted it here.

Problem

Citing from ?.Machine

double.eps
the smallest positive floating-point number x such that 1 + x != 1. It equals double.base ^ ulp.digits if either double.base is 2 or double.rounding is 0; otherwise, it is (double.base ^ double.ulp.digits) / 2. Normally 2.220446e-16.

Thus, I would assume that all.equal(1 + .Machine$double.eps, 1.0) returns FALSE. Which it does not. Reading the doc of all.equal I see that the default tolerance is .Machine$double.eps ^ 0.5.

Fair enough, but I observe some odd results which I do not understand:

isTRUE(all.equal(1.0 + .Machine$double.eps, 1.0, tolerance = .Machine$double.eps)) # TRUE
isTRUE(all.equal(1.0 - .Machine$double.eps, 1.0, tolerance = .Machine$double.eps)) # FALSE
isTRUE(all.equal(0.9 + .Machine$double.eps, 0.9, tolerance = .Machine$double.eps)) # FALSE
isTRUE(all.equal(2.0 + .Machine$double.eps, 2.0, tolerance = .Machine$double.eps)) # TRUE

Thus, all.equal picks only differences for numbers below 1 correctly.

Last explanation I could think of is that all.equal looks on the relative difference scale by default, so I tried to overrule this behaviour with no success either:

isTRUE(all.equal(1.0 + .Machine$double.eps, 1.0, 
                 tolerance = .Machine$double.eps, scale = 1)) # TRUE

Apparently, I have a massive misunderstanding of how floating-point numbers work in R, which leads me to these

Questions

Upvotes: 0

Views: 1126

Answers (1)

GKi
GKi

Reputation: 39717

.Machine$double.eps is the difference between 1 and the smallest representable value greater than 1. The difference between 0.1 and the smallest representable value greater than 0.1 is smaller than .Machine$double.eps and the difference between 100 and the smallest representable value greater than 100 is larger than .Machine$double.eps. Have a look at: What is the correct/standard way to check if difference is smaller than machine precision?.

.Machine$double.eps is

.Machine$double.eps
[1] 2.220446e-16

When you make the calculations the intern sotred values will be approximately:

print(1.0 + .Machine$double.eps, 20)
#[1] 1.000000000000000222
print(1.0 - .Machine$double.eps, 20)
#[1] 0.99999999999999977796
print(0.9 + .Machine$double.eps, 20)
#[1] 0.90000000000000024425
print(2.0 + .Machine$double.eps, 20)
#[1] 2

Using tolerance = .Machine$double.eps all.equal returns TRUE or FALSE depending if the difference of the intern stored values is lager or not than tolerance.

To compare 2 numbers in R if the are intern stored equal use ==.

Upvotes: 1

Related Questions