2011-07-07 254 views
24

在R中將數字轉換爲基數2(在字符串中,例如5將轉換爲"0000000000000101")最簡單的方法是什麼?有intToBits,但它返回一個字符串矢量,而不是一個字符串:在R中將十進制轉換爲二進制?

> 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" 
+1

'intToBits' _不_返回一個字符串矢量。它返回一個原始矢量。注意矢量有32個元素。這是每個位的一個元素(因爲R使用32位整數)。我想不出將數字表示爲字符串的情況是有用的......你想要做什麼? –

+0

我正在研究一些密碼分析的例子,很高興能夠將密鑰顯示爲位序列,「011010110」等。 – Jay

+1

@Jay:R不是GNU –

回答

17

@尼科的回答略有延長。這消除了領先的「0」,從每一位:

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

那裏有一個額外的'rev',但刪除它完美的作品!謝謝! – Jay

+0

@Jay:固定。我的Ctrl + C/Ctrl + V技能缺乏。 –

+0

太多東西,什麼是一個乾淨的方法來解決這個問題? – bubakazouba

22

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

pastecollapse參數將矢量摺疊爲字符串。您必須使用rev才能獲得正確的字節順序。

as.integer去除多餘的零

+0

使用'rev' ...除非你在Sun系統上。 ;-) –

+0

嗯,但每一位都被列爲兩位數字:'00'或'01' ...有沒有辦法讓'intToBits'返回的原始向量只寫一位數字? – Jay

+0

我用另一種更簡單的方法更新了答案。 – nico

12

我認爲,可以使用R.utils包,則intToBin()函數

>library(R.utils) 

>intToBin(12) 
[1] "1100" 

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

該函數將採取的十進制數,並返回對應的二進制序列,即1: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) 
} 
+0

我認爲最好寫y%/%2 – skan

2

哦,但是如果你有一個64位整數作爲由bit64包啓用怎麼辦?除了@epwalsh之外,每個給出的答案都不會對64位整數進行操作,因爲R和R.utils的基於C的內部結構不支持它。如果你首先加載bit64包,除了R(使用循環),狗慢(所有速度都是相對的),@ epwalsh的解決方案非常好,並且可以在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 

```

+1

...我現在注意到這完全是荒謬的,因爲bit64有一個as.bitstring函數,它的速度是我的Rcpp函數的兩倍......但我會在這裏作爲愚蠢的紀念碑,並作爲一個潛在的提示,告訴我們如何從整數64到C++之間的銜接,然後回到......但如果您需要更有效的方法來做到這一點,請務必查看bit64源代碼。 – russellpierce

5

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" 
+0

我不需要轉換這麼大的數字,但無論如何都是很好的答案! +1 – Jay

+1

我遇到了一個問題,我需要使用大數字來操作,並且在搜索完解決方案後,最終編寫了我自己的代碼:) – inscaven

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 
-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 
} 
+0

儘管此代碼可能會回答問題,提供有關** how **和* *爲什麼它解決了問題會提高答案的長期價值。 – Alexander