如何检查数字是2的幂?以下是我到目前为止所提出的:
# check every number in a vector
y <- 1:100000000
x <- 2^(0:100)
y %in% x
y[(y %in% x)==TRUE]
# check a single number
y <- 250000
x <- 2^(0:100)
y %in% x
# check a single random number
y <- sample(1000000000,1)
x <- 2^(0:100)
y %in% x
有更好的方法吗?上面的方法对我来说似乎并不是很普遍,并且由于舍入错误而导致数据非常大,因此失败:
# 2^95 = 39,614,081,257,132,168,796,771,975,168
# correct
y <- 39614081257132168796771975168
x <- 2^(0:100)
y %in% x
# incorrect
y <- 39614081257132168796771975167
x <- 2^(0:100)
y %in% x
对于其他语言,Stack Overflow上有许多类似的问题,答案似乎涉及位模式。这种方法可以与R
一起使用吗?与那种方法相比,我的方法似乎并不复杂,我认为可能有更好的方法。谢谢你的任何建议。
答案 0 :(得分:4)
根据请求,发布bigz
巨号的解决方案:
注意:as.character
- 类数字的bigz
方法采用参数b
,该参数指定在转换为字符之前将数字转换为的基数。
> bar<-as.bigz(2)^95;
> bar
Big Integer ('bigz') :
[1] 39614081257132168796771975168
> as.character(bar,b=2)
[1] "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
> foo<-prev
> table(unlist(strsplit(foo,'')))
0 1
95 1
或者,对于2的非权力,
> bbar<-bar+1
> table(unlist(strsplit(as.character(bbar,b=2),'')))
0 1
94 2
答案 1 :(得分:3)
是的,您可以查看R中的位模式:
isPowerOf2 <- function(x) {
n1s <- sum(as.numeric(intToBits(x)))
if (n1s == 1) {
return(TRUE)
} else {
return(FALSE)
}
}
答案 2 :(得分:2)
根据我的评论,这是one of the algorithms (#9)的实现,使用数字的二进制表示的比较。 注意:这假定x
是一个整数。
two <- function(x) {
if(x<2)
return(FALSE)
else
!any(as.logical(intToBits(x) & intToBits(x-1)))
}
twov <- Vectorize(two) # vectorize the `two` function
一些示例结果:
> cbind(0:20, twov(0:20))
[,1] [,2]
[1,] 0 0
[2,] 1 0
[3,] 2 1
[4,] 3 0
[5,] 4 1
[6,] 5 0
[7,] 6 0
[8,] 7 0
[9,] 8 1
[10,] 9 0
[11,] 10 0
[12,] 11 0
[13,] 12 0
[14,] 13 0
[15,] 14 0
[16,] 15 0
[17,] 16 1
[18,] 17 0
[19,] 18 0
[20,] 19 0
[21,] 20 0
> twov(2^(0:10))
[1] FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
答案 3 :(得分:0)
您受计算机可以处理的最大整数限制。例如:如果您使用的是32位R,那么最大值为.Machine$integer.max
。没有。你正在使用2 ^ 95超出R或任何64位计算机的范围 - 因此它被转换为浮点数并且不完全代表内部的整数39614081257132168796771975168
。
对于处理非常大的数字,你必须查看可以做到这一点的特殊库 - 但是,我不知道任何。 [在Java中,那将是BigInteger
]。
否则,检查log2(整数)应该没问题。
答案 4 :(得分:0)
我比较了我原来的方法和三个答案中使用的方法。假设我正确地进行了比较,结果似乎表明,如果你将自己限制在相对较小的数字,那么所有四种方法都能正常工作,而我原来的方法是最快的。
然而,如果你处理的是非常大的数字,那么Carl Witthoft的方法就可以了。在这方面,卡尔可能应该得到勾选标记。虽然其他答案也很好。我认为,但并非100%肯定,Carl的方法使用位模式,正如比较的其他两个答案中的方法一样。
很抱歉,如果我在下面的代码中犯了任何错误。
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
答案 5 :(得分:0)
这是java实现:
public class FindPowerOfTwo {
static int input = 7;
public static void main(String[] args) {
System.out.println(validate(input));
}
private static boolean validate(int n) {
System.out.println(n & (n-1));
return (n > 0) && ((n & (n - 1)) == 0);
}
}
这是使用按位运算的优化解决方案。