On Sep 8, 2011, at 4:41 PM, Marc Schwartz wrote:


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.

Out of interest I tested whether my guess that half of the squared- sqrt's would fail and it was not even close to 50%. So I took the testing further and cannot explain the results:

> sum(sapply(sqrt(2:10000)^2, is.whole))
[1] 7577
> sum(sapply(((2:10000)^(1/3) )^3, is.whole))
[1] 49                                # No that _is_ strange.
> sum(sapply(((2:10000)^(1/4) )^4, is.whole))
[1] 6207
> sum(sapply(((2:10000)^(1/5) )^5, is.whole))
[1] 9946
> sum(sapply(((2:10000)^(1/6) )^6, is.whole))
[1] 1324

Pondering the irregular pattern of results above is probably entirely tangential. I think that if a number "should" have been an integer it should have been defined as an integer and otherwise being close enough on either side of an integer value should be enough.

 is.whole2 <- 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, round(a,0))) ||
    (is.complex(a) && {ri <- c(Re(a),Im(a)); is.eq(ri, floor(ri))})
 }

> sum(sapply(((2:10000)^(1/3) )^3, is.whole2))
[1] 9999
> sum(sapply(((2:10000)^(1/5) )^5, is.whole2))
[1] 9999



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


David Winsemius, MD
West Hartford, CT

______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to