在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"
答案 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
}