# [R] The elegant way to test if a number is a whole number

David Winsemius dwinsemius at comcast.net
Thu Sep 8 22:09:24 CEST 2011

```On Sep 8, 2011, at 3:54 PM, Marc Schwartz wrote:

>
> On Sep 8, 2011, at 2:42 PM, David Winsemius wrote:
>
>>
>> On Sep 8, 2011, at 3:35 PM, Alexander Engelhardt wrote:
>>
>>> Am 08.09.2011 20:48, schrieb Marc Schwartz:
>>>> There was a post from Martin Maechler some years ago and I had to
>>>> search a bit to find it. For these sorts of issues, I typically
>>>> trust his judgement.
>>>>
>>>> The post is here:
>>>>
>>>>   https://stat.ethz.ch/pipermail/r-help/2003-April/032471.html
>>>>
>>>> His solution also handles complex numbers.
>>>
>>> For those too lazy to follow
>>> He is basically creating the function is.whole:
>>>
>>>  is.whole <- function(x)
>>>    is.numeric(x) && floor(x)==x
>>
>> Are you sure? I thought the test would have been all.equal(x,
>> round(x,0) )
>>
>> My reasoning was that 1.999999999999 should be considered 2 but
>> floor would make it 1.
>
> David, I am confuzzled. Why would that be equal to 2?

So that sqrt(3) * sqrt(3) would be a "whole number". (It is true the
the floor based wholeness criterion would make sqrt(2)*sqrt(2)

Somehow it doesn't see "right" that only half of square roots of
integers that have been squared should pass the wholeness test:

> is.whole <- function(a, tol = 1e-7) {
+    is.eq <- function(x,y) {
+ 	 r <- all.equal(x,y, tol=tol)
+ 	 is.logical(r) && r
+    }
+    (is.numeric(a) && is.eq(a, floor(a))) ||
+    (is.complex(a) && {ri <- c(Re(a),Im(a)); is.eq(ri, floor(ri))})
+ }
> is.whole( sqrt(2)^2 )
[1] TRUE
> is.whole( sqrt(3)^2  )
[1] FALSE

>
>> x == 2
> [1] FALSE
>
>> 2 - x
> [1] 1.000089e-12
>
> # The default tolerance is .Machine\$double.eps ^ 0.5
>> all.equal(x, 2, tol = .Machine\$double.eps)
> [1] "Mean relative difference: 5.000445e-13"
>
>> all.equal(x, 2, tol = .Machine\$double.eps ^ 0.5)
> [1] TRUE
>
>>
>>> x=1.999999999999
>>> x
>> [1] 2
>
>> print(x, 15)
> [1] 1.999999999999
>
>>> floor(x)
>> [1] 1
>>> isTRUE(all.equal(x, floor(x)))
>> [1] FALSE
>>> all.equal(x, round(x,0))
>> [1] TRUE
>>
>>
>>>
>>> Seems like the most appropriate way now. I'll make it so!
>
> Very apropos on the 45th anniversary of Star Trek. :-)
>
>>> Thanks for your help :-)
>>> -- Alex
>
> Cheers,
>
> Marc
>

David Winsemius, MD
West Hartford, CT

```