The help page for ?is.integer
has a note about a function that will tell us if a value is an integer:
is.wholenumber <-
function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
What could be the argument to use sqrt(eps)
as tolerance here? Also, is there a good reason to use anything else than tol=0
?
The background is my answer on this question. Some commenters objected to this function.
My simple minded hypothesis: this is done to make it close in behavior to print (which has a default of 7 decimal digits). E.g.:
> 1.000005
[1] 1.000005
> 1.0000000005
[1] 1
> is.wholenumber(1.000005)
[1] FALSE
> is.wholenumber(1.0000000005)
[1] TRUE
It does not work perfectly though:
> 1.00000005
[1] 1
> is.wholenumber(1.00000005)
[1] FALSE
There is a better argument in the comments below: the sqrt(eps)
may be a (rough) estimate of the round-off error caused by floating-point operations.
Compare
> is.wholenumber(0.6/0.2, tol=0)
[1] FALSE
> is.wholenumber(0.6/0.2)
[1] TRUE
While 3 == 0.6/0.3
exactly in reality, it is not so in floating point representation.
From the helpfile for "=="
For numerical and complex values, remember ‘==’ and ‘!=’ do not allow for the finite representation of fractions, nor for rounding error. Using ‘all.equal’ with ‘identical’ is almost always preferable.
The default tolerance for is.wholenumber
is set to the same amount as in all.equal
:
## S3 method for class 'numeric'
all.equal(target, current,
tolerance = .Machine$double.eps ^ 0.5, scale = NULL,
..., check.attributes = TRUE)
This means that the default behavior of is.wholenumber
is comparable to
isTRUE(all.equal(0,abs(x - round(x))))
To take our example full circle
> x <- 0.6/0.2
> x
[1] 3
> round(x)
[1] 3
> x == round(x)
[1] FALSE
> isTRUE(all.equal(0,x-round(x)))
[1] TRUE
> isTRUE(all.equal(0,x-round(x), tol=0))
[1] FALSE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With