I compared my original approach and the approaches used in three of the answers. Assuming I performed the comparisons correctly, the results seem to indicate that if you are restricting yourself to relatively small numbers then all four approaches work correctly, and my original approach is fastest.
However, if you are dealing with extremely large numbers only Carl Witthoft's approach will work. In that light, Carl probably deserves the checkmark. Although the other answers are nice too. I think, but am not 100% certain, that Carl's approach uses bit patterns, as do the methods in the two other answers being compared.
Sorry if I made any errors in the code below.
library(gmp)
my.data1 <- read.table(text='
my.number is.it.a.power.of.2
2 TRUE
3 FALSE
8 TRUE
100 FALSE
65536 TRUE
100000 FALSE
1200000 FALSE
268435456 TRUE
140737488355328 TRUE
140737488355330 FALSE
39614081257132168796771975168 TRUE
39614081257132168796771975112 FALSE
', header = TRUE, colClasses=c('numeric', 'logical'))
my.data2 <- read.table(text='
my.number is.it.a.power.of.2
2 TRUE
3 FALSE
8 TRUE
100 FALSE
65536 TRUE
100000 FALSE
1200000 FALSE
268435456 TRUE
140737488355328 TRUE
140737488355330 FALSE
39614081257132168796771975168 TRUE
39614081257132168796771975112 FALSE
', header = TRUE, colClasses=c('character', 'logical'))
###############################################################
my.function <- function(m) {
x <- 2^(0:100)
return(m %in% x)
}
my.functionv <- Vectorize(my.function)
###############################################################
two <- function(x) {
if(x<2)
return(FALSE)
else
!any(as.logical(intToBits(x) & intToBits(x-1)))
}
twov <- Vectorize(two) # vectorize the `two` function
###############################################################
isPowerOf2 <- function(x) {
n1s <- sum(as.numeric(intToBits(x)))
if (n1s == 1) {
return(TRUE)
} else {
return(FALSE)
}
}
isPowerOf2v <- Vectorize(isPowerOf2)
###############################################################
Carls.function <- function(x) {
bar <- as.bigz(x)
if(dim(table(unlist(strsplit(as.character(bar,b=2),'')))) == 1) {
return(as.numeric(table(unlist(strsplit(as.character(bar,b=2),'')))[1]) == 1)
}
else if(dim(table(unlist(strsplit(as.character(bar,b=2),'')))) == 2) {
return(as.numeric(table(unlist(strsplit(as.character(bar,b=2),'')))[2]) == 1)
}
}
Carls.functionv <- Vectorize(Carls.function)
###############################################################
m1 <- my.data1$my.number
f1.1 <- my.functionv(m1) ; names(f1.1) <- NULL
f1.2 <- twov(m1) ; names(f1.2) <- NULL
f1.3 <- isPowerOf2v(m1) ; names(f1.3) <- NULL
f1.4 <- Carls.functionv(m1) ; names(f1.4) <- NULL
all.equal(f1.1, my.data1$is.it.a.power.of.2)
all.equal(f1.2, my.data1$is.it.a.power.of.2)
all.equal(f1.3, my.data1$is.it.a.power.of.2)
all.equal(f1.4, my.data1$is.it.a.power.of.2)
m2 <- my.data2$my.number
f2.1 <- my.functionv(m2) ; names(f2.1) <- NULL
f2.2 <- twov(m2) ; names(f2.2) <- NULL
f2.3 <- isPowerOf2v(m2) ; names(f2.3) <- NULL
f2.4 <- Carls.functionv(m2) ; names(f2.4) <- NULL
all.equal(f2.1, my.data2$is.it.a.power.of.2)
all.equal(f2.2, my.data2$is.it.a.power.of.2)
all.equal(f2.3, my.data2$is.it.a.power.of.2)
all.equal(f2.4, my.data2$is.it.a.power.of.2)
m3 <- my.data1$my.number[1:7]
f3.1 <- my.functionv(m3) ; names(f3.1) <- NULL
f3.2 <- twov(m3) ; names(f3.2) <- NULL
f3.3 <- isPowerOf2v(m3) ; names(f3.3) <- NULL
f3.4 <- Carls.functionv(m3) ; names(f3.4) <- NULL
f3.5 <- my.function(m3) ; names(f3.5) <- NULL
all.equal(f3.1, my.data1$is.it.a.power.of.2[1:7])
all.equal(f3.2, my.data1$is.it.a.power.of.2[1:7])
all.equal(f3.3, my.data1$is.it.a.power.of.2[1:7])
all.equal(f3.4, my.data1$is.it.a.power.of.2[1:7])
all.equal(f3.5, my.data1$is.it.a.power.of.2[1:7])
###############################################################
library(microbenchmark)
m3 <- my.data1$my.number[1:7]
microbenchmark(my.functionv(m3) , my.function(m3),
twov(m3) ,
isPowerOf2v(m3) ,
Carls.functionv(m3),
times = 2000)
###############################################################
Unit: microseconds
expr min lq median uq max neval
my.functionv(m3) 315.956 499.921 508.810 532.0625 3671.775 2000
my.function(m3) 31.459 52.659 54.028 62.9180 134.042 2000
twov(m3) 152.507 240.044 247.567 272.1870 5550.404 2000
isPowerOf2v(m3) 152.507 242.780 249.618 269.1095 2455.829 2000
Carls.functionv(m3) 7486.481 7992.213 8092.402 8278.0765 52285.679 2000