Reputation: 20409
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 numberx
such that1 + x != 1
. It equalsdouble.base ^ ulp.digits
if eitherdouble.base
is 2 ordouble.rounding
is 0; otherwise, it is(double.base ^ double.ulp.digits) / 2
. Normally2.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
all.equal
different for numbers below and above 1
?.Machine$double.eps ^ .5
as default tolerance instead of the unsquarerooted version? Is it simply to relax the test a bit?Upvotes: 0
Views: 1126
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