在R中将十进制转换为二进制?

时间:2011-07-07 16:59:52

标签: r

在R中将数字转换为基数2(在字符串中,例如5将转换为"0000000000000101")的最简单方法是什么?有intToBits,但它返回字符串向量而不是字符串:

> intToBits(12)
 [1] 00 00 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[26] 00 00 00 00 00 00 00

我尝试了其他一些功能,但没有成功:

> toString(intToBits(12))
[1] "00, 00, 01, 01, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00"

10 个答案:

答案 0 :(得分:24)

paste(rev(as.integer(intToBits(12))), collapse="")完成工作

带有paste参数的

collapse会将矢量折叠为字符串。您必须使用rev来获取正确的字节顺序。

as.integer删除多余的零

答案 1 :(得分:18)

请注意intToBits()返回'原始'向量,而不是字符向量(字符串)。请注意,我的答案是@nico's original answer的轻微扩展,从每个位中删除前导“0”:

paste(sapply(strsplit(paste(rev(intToBits(12))),""),`[[`,2),collapse="")
[1] "00000000000000000000000000001100"

为了清晰起见,要分解这些步骤:

# bit pattern for the 32-bit integer '12'
x <- intToBits(12)
# reverse so smallest bit is first (little endian)
x <- rev(x)
# convert to character
x <- as.character(x)
# Extract only the second element (remove leading "0" from each bit)
x <- sapply(strsplit(x, "", fixed = TRUE), `[`, 2)
# Concatenate all bits into one string
x <- paste(x, collapse = "")
x
# [1] "00000000000000000000000000001100"

或者,作为@nico showed,我们可以使用as.integer()作为更简洁的方法从每个位中删除前导零。

x <- rev(intToBits(12))
x <- paste(as.integer(x), collapse = "")
# [1] "00000000000000000000000000001100"

只是为了方便复制 - 粘贴,这里是上面的函数版本:

dec2bin <- function(x) paste(as.integer(rev(intToBits(x))), collapse = "")

答案 2 :(得分:15)

我认为您可以使用R.utils包,然后使用intToBin()函数

>library(R.utils)

>intToBin(12)
[1] "1100"

> typeof(intToBin(12))
[1] "character"

答案 3 :(得分:7)

intToBits限制为最大2 ^ 32,但如果我们想将1e10转换为二进制,该怎么办?这是将浮点数转换为二进制数的函数,假设它们是存储为numeric的大整数。

dec2bin <- function(fnum) {
  bin_vect <- rep(0, 1 + floor(log(fnum, 2)))
  while (fnum >= 2) {
    pow <- floor(log(fnum, 2))
    bin_vect[1 + pow] <- 1
    fnum <- fnum - 2^pow
  } # while
  bin_vect[1] <- fnum %% 2
  paste(rev(bin_vect), collapse = "")
} #dec2bin

此功能在2 ^ 53 = 9.007199e15之后开始松散数字,但适用于较小的数字。

microbenchmark(dec2bin(1e10+111))
# Unit: microseconds
#                 expr     min       lq     mean   median      uq    max neval
# dec2bin(1e+10 + 111) 123.417 125.2335 129.0902 126.0415 126.893 285.64   100
dec2bin(9e15)
# [1] "11111111110010111001111001010111110101000000000000000"
dec2bin(9e15 + 1)
# [1] "11111111110010111001111001010111110101000000000000001"
dec2bin(9.1e15 + 1)
# [1] "100000010101000110011011011011011101001100000000000000"

答案 4 :(得分:6)

看一下R.utils包 - 你有一个名为intToBin的函数......

http://rss.acs.unt.edu/Rdoc/library/R.utils/html/intToBin.html

答案 5 :(得分:5)

哦,但如果bit64包启用了64位整数怎么办?除了@epwalsh之外,给出的每个答案都不会对64位整数进行操作,因为R和R.utils的基于C的内部不支持它。 @ epwalsh的解决方案非常棒,如果先加载bit64包,则在R中工作,除了它(使用循环)在R中是狗慢(所有速度都是相对的)。

o.dectobin <- function(y) {
  # find the binary sequence corresponding to the decimal number 'y'
  stopifnot(length(y) == 1, mode(y) == 'numeric')
  q1 <- (y / 2) %/% 1
  r <- y - q1 * 2
  res = c(r)
  while (q1 >= 1) {
    q2 <- (q1 / 2) %/% 1
    r <- q1 - q2 * 2
    q1 <- q2
    res = c(r, res)
  }
  return(res)
}

dat <- sort(sample(0:.Machine$integer.max,1000000))
system.time({sapply(dat,o.dectobin)})
#   user  system elapsed 
# 61.255   0.076  61.256 

如果我们对其进行字节编译,我们可以做得更好......

library(compiler)
c.dectobin <- cmpfun(o.dectobin)
system.time({sapply(dat,c.dectobin)})
#   user  system elapsed 
# 38.260   0.010  38.222 

......但它仍然很慢。如果我们用C编写自己的内部函数,我们可以大大加快速度(这是我在这里借用@ epwalsh的代码借来的 - 显然我不是C程序员)......

library(Rcpp)
library(inline)
library(compiler)
intToBin64.worker <- cxxfunction( signature(x = "string") , '    
#include <string>
#include <iostream>
#include <sstream>
#include <algorithm>
// Convert the string to an integer
std::stringstream ssin(as<std::string>(x));
long y;
ssin >> y;

// Prep output string
std::stringstream ssout;


// Do some math
int64_t q2;
int64_t q1 = (y / 2) / 1;
int64_t r = y - q1 * 2;
ssout << r;
while (q1 >= 1) {
q2 = (q1 / 2) / 1;
r = q1 - q2 * 2;
q1 = q2;
ssout << r;
}


// Finalize string
//ssout << r;
//ssout << q1;
std::string str = ssout.str();
std::reverse(str.begin(), str.end());
return wrap(str);
', plugin = "Rcpp" )

system.time(sapply(as.character(dat),intToBin64.worker))
#   user  system elapsed 
#  7.166   0.010   7.168 

```

答案 6 :(得分:3)

此函数将采用十进制数并返回相应的二进制序列,即1和0的向量

dectobin <- function(y) {
  # find the binary sequence corresponding to the decimal number 'y'
  stopifnot(length(y) == 1, mode(y) == 'numeric')
  q1 <- (y / 2) %/% 1
  r <- y - q1 * 2
  res = c(r)
  while (q1 >= 1) {
    q2 <- (q1 / 2) %/% 1
    r <- q1 - q2 * 2
    q1 <- q2
    res = c(r, res)
  }
  return(res)
}

答案 7 :(得分:2)

尝试»binaryLogic«

library(binaryLogic)

ultimate_question_of_life_the_universe_and_everything <- as.binary(42)

summary(ultimate_question_of_life_the_universe_and_everything)
#>   Signedness  Endianess value<0 Size[bit] Base10
#> 1   unsigned Big-Endian   FALSE         6     42

> as.binary(0:3, n=2)
[[1]]
[1] 0 0

[[2]]
[1] 0 1

[[3]]
[1] 1 0

[[4]]
[1] 1 1

答案 8 :(得分:1)

- 最初作为@JoshuaUlrich答案的编辑添加,因为它完全是他和@ nico的推论;他建议我添加一个单独的答案,因为它在他的肯定之外引入了一个包 -

由于@ JoshuaUlrich的答案非常实用(6个背靠背函数),我发现%>% / magrittr的管道(tidyverse)运算符使得以下解决方案更优雅:

library(magrittr)

intToBits(12) %>% rev %>% as.integer %>% paste(collapse = '')
# [1] "00000000000000000000000000001100"

我们还可以添加一个最终as.integer调用来截断所有前导零:

intToBits(12) %>% rev %>% as.integer %>% paste(collapse = '') %>% as.integer
# [1] 1100

(当然注意,这再次存储为integer,意味着R将其视为基数10中表示的1100,而不是基数2中表示的12)

请注意,@ ramanudle(及其他人,尤其是@russellpierce,提供C ++实现)方法通常是低级语言中提出的标准,因为它是一种非常有效的方法(它适用于任何可以存储在R中的数字,即不限于integer范围。)

另外值得一提的是C implementation of intToBits非常简单(除了我不知道C中的&>>=运算符)

答案 9 :(得分:-2)

decimal.number<-5

i=0

result<-numeric()

while(decimal.number>0){

  remainder<-decimal.number%%2

  result[i]<-remainder

  decimal.number<-decimal.number%/%2

  i<-i+1
}