转换数字中的二进制样本

时间:2015-11-20 14:05:57

标签: r binary numbers

我有这样的二进制样本:

Z = c(0,0,0,1,0,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,0)

我想转换长度为4的所有序列,即:

我需要阅读原始二进制样本并将所有可能的长度为4的序列转换为数字。

示例:序列0000为1,序列0001为2,序列0010为3,...,序列1111为16。

预期输出应该是由数字1,2,3,... 16形成的新样本,其长度与原始样本相同:

Z = c(0,0,0,1,0,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,0)

Z1 = c(2,3,6,12,8,15,14,11,5,10,3,11,6,12,8,15,14,11,6,11)

我怎么能在R?中做到这一点?

4 个答案:

答案 0 :(得分:3)

尝试:

z<-c(0,0,0,1,0,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,0)
y<-as.character(z)
z1<-sapply(1:(length(y)-3),function(x){strtoi(paste(y[x:(x+3)],collapse=''),2)+1})

[1]  2  3  6 12  8 15 14 11  5 10  3  6 11  6 12  8 15 14 11  6 11

代码的工作原理如下:

  • 将向量z转换为字符向量(y
  • 的长度为y减3(因为每个数字需要4位数),请应用strtoi函数

strtoi函数通过指定输入数字的基数来转换数字(此处为2,因为它是二进制数)。我们加1,因为二进制0000等于0而不是1。

注意:转换为字符是可选的,您可以直接执行

sapply(1:(length(z)-3),function(x){strtoi(paste(z[x:(x+3)],collapse=''),2)+1})

使用vapply

也会更快
vapply(1:(length(z)-3),function(x){strtoi(paste(z[x:(x+3)],collapse=''),2)+1},FUN.VALUE=1)

Unit: microseconds
   expr     min      lq     mean   median      uq     max neval cld
 vapply 206.866 209.111 214.3936 210.0735 211.356 338.362   100  a 
 sapply 230.278 231.882 234.0249 232.8440 234.128 273.897   100   b

答案 1 :(得分:3)

这是另一种方法:

Z <- c(0,0,0,1,0,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,0)
Z.tmp <- embed(Z,4)
Z1 <- as.vector(Z.tmp %*% c(1,2,4,8) + 1)

答案 2 :(得分:2)

您也可以使用

library(zoo)
library(compositions)
unbinary(rollapply(z,4, FUN= paste, collapse=''))+1L
#[1]  2  3  6 12  8 15 14 11  5 10  3  6 11  6 12  8 15 14 11  6 11

答案 3 :(得分:0)

因为您将4位二进制数转换为十进制数,所以公式为:

  

dec = x1 * 2 ^ 3 + x2 * 2 ^ 2 + x3 * 2 ^ 1 + x4 * 2 ^ 0

这可以通过R实现扫描乘法

来实现

dec <- sum( X * c(8,4,2,1) )

OR向量乘法(显示为@Greg Snow)。

dec <- X %*% c(8,4,2,1)

最后,使用这个计算模式到sapply的每4个数组元素,然后整个代码如下。

Z <- c(0,0,0,1,0,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,0)
Z.len  <- length(Z)

# stand for 2^3, 2^2, 2^1, 2^0
Z.base <- c(8,4,2,1)

res1 <- sapply(1:(Z.len-3), FUN=function(x) sum(Z[x:(x+3)] * Z.base)+1 )
res2 <- sapply(1:(Z.len-3), FUN=function(x) (Z[x:(x+3)] %*% Z.base)+1 )
all.equal(res1, res2)
#[1] TRUE 
res1
# [1]  2  3  6 12  8 15 14 11  5 10  3  6 11  6 12  8 15 14 11  6 11