[R] The elegant way to test if a number is a whole number
Marc Schwartz
marc_schwartz at me.com
Thu Sep 8 22:41:26 CEST 2011
On Sep 8, 2011, at 3:09 PM, David Winsemius wrote:
>
> 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
>
<snip content>
OK. I suspect it may down to what assumptions one is willing to make, including the level of tolerance used for the comparison.
is.whole() of course works for 2 because:
> print(sqrt(2) ^ 2, 20)
[1] 2.0000000000000004441
is slightly larger than 2, so:
> floor(sqrt(2) ^ 2)
[1] 2
works, as does:
> round(sqrt(2) ^ 2, 0)
[1] 2
On the other hand:
> print(sqrt(3) ^ 2, 20)
[1] 2.9999999999999995559
is slightly smaller than 3, so:
> floor(sqrt(3) ^ 2)
[1] 2
versus:
> round(sqrt(3) ^ 2, 0)
[1] 3
Not sure if Martin (cc'd now) might have any comments 8 plus years later relative to this issue, as I would again defer to his judgement here.
The other solution proposed, using modulo division, would logically fail in both cases:
> (sqrt(3) ^ 2) %% 1 == 0
[1] FALSE
> (sqrt(2) ^ 2) %% 1 == 0
[1] FALSE
Regards,
Marc
More information about the R-help
mailing list