是一个2的幂

时间:2014-03-04 10:37:03

标签: r largenumber

如何检查数字是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一起使用吗?与那种方法相比,我的方法似乎并不复杂,我认为可能有更好的方法。谢谢你的任何建议。

6 个答案:

答案 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);
     }
  }

这是使用按位运算的优化解决方案。