2011-07-07 73 views
24

Điều gì sẽ là cách dễ nhất để chuyển đổi một số thành cơ số 2 (trong một chuỗi, ví dụ 5 sẽ được chuyển thành "0000000000000101") trong R? Có intToBits, nhưng nó sẽ trả về một vector của chuỗi chứ không phải là một chuỗi:Chuyển đổi số thập phân thành nhị phân trong 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 

Tôi đã thử một số chức năng khác, nhưng đã không thành công:

> 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' không _not_ trả về một vector của chuỗi. Nó trả về một vector nguyên. Chú ý rằng vector có 32 phần tử. Đó là một phần tử cho mỗi bit (vì R sử dụng các số nguyên 32 bit). Tôi không thể nghĩ về một tình huống mà nó sẽ hữu ích để đại diện cho một số như một chuỗi chữ của bit ... bạn đang cố gắng làm gì? –

+0

Tôi đang làm việc trên một số ví dụ về giải mã, và thật tuyệt khi có thể hiển thị các phím dưới dạng chuỗi bit, "011010110", v.v. – Jay

+1

@Jay: R không phải là GNU –

Trả lời

17

Một phần mở rộng nhẹ trả lời @ nico của. Điều này loại bỏ hàng đầu "0" từ mỗi bit:

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

Có thêm một 'rev' ở đó, nhưng loại bỏ nó hoạt động hoàn hảo! Cảm ơn! – Jay

+0

@Jay: đã được sửa. Kỹ năng Ctrl + C/Ctrl + V của tôi đang thiếu. –

+0

quá nhiều bit tho, cách sạch sẽ để khắc phục điều đó là gì? – bubakazouba

22

paste(rev(as.integer(intToBits(12))), collapse="") hiện công việc

paste với tham số collapse thu gọn vectơ thành chuỗi. Bạn phải sử dụng rev để có được thứ tự byte chính xác.

as.integer loại bỏ các số không thêm

+0

Sử dụng 'rev' ... trừ khi bạn đang sử dụng hệ thống Sun. ;-) –

+0

Hm, nhưng mỗi bit được liệt kê dưới dạng hai chữ số: '00' hoặc' 01' ... Có cách nào để lấy vectơ thô trả về bởi 'intToBits' và viết mỗi bit chỉ bằng một chữ số không? – Jay

+0

Tôi đã cập nhật câu trả lời bằng một cách dễ dàng hơn để thực hiện điều đó. – nico

12

Tôi nghĩ rằng bạn có thể sử dụng gói R.utils, sau đó hàm intToBin()

>library(R.utils) 

>intToBin(12) 
[1] "1100" 

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

Hàm này sẽ lấy một số thập phân và trả về trình tự nhị phân tương ứng, vectơ 1 's and 0's

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

Tôi nghĩ tốt hơn là viết y% /% 2 – skan

2

Ồ, nhưng phải làm gì nếu bạn có số nguyên 64 bit được kích hoạt bởi gói bit64? Mỗi câu trả lời được đưa ra, khác với câu trả lời của @epwalsh sẽ không hoạt động trên số nguyên 64 bit vì C dựa trên internals của R và R.utils không hỗ trợ nó. @ epwalsh của giải pháp là rất tốt và làm việc trong R nếu bạn tải gói bit64 đầu tiên, ngoại trừ nó (sử dụng vòng) trong R là con chó chậm (tất cả các tốc độ là tương đối).

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 

Chúng ta có thể làm tốt hơn nếu chúng ta bytes biên dịch nó ...

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

... nhưng nó vẫn còn khá chậm. Chúng tôi có thể nhận được nhanh hơn đáng kể nếu chúng ta viết internals riêng của chúng tôi trong C (đó là những gì tôi đã làm ở đây vay từ mã @ epwalsh của - Tôi không phải là một lập trình viên C, rõ ràng) ...

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

... mà bây giờ tôi nhận thấy là vô lý vì bit64 có hàm as.bitstring nhanh gấp hai lần hàm Rcpp của tôi ... nhưng tôi sẽ để lại ở đây như một tượng đài cho sự điên rồ và như một lời nhắc nhở tiềm năng về cách cầu nối từ số nguyên64 đến C++ và ngược lại ... nhưng chắc chắn thấy mã nguồn bit64 nếu bạn cần một cách hiệu quả hơn để làm điều đó. – russellpierce

5

intToBits được giới hạn tối đa 2^32, nhưng điều gì sẽ xảy ra nếu chúng tôi muốn chuyển đổi 1e10 thành nhị phân? Đây là hàm để chuyển đổi số float thành nhị phân, giả sử chúng là số nguyên lớn được lưu trữ là 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 

Chức năng này bắt đầu mất chữ số sau 2^53 = 9.007199e15, nhưng hoạt động tốt đối với số nhỏ hơn.

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

Tôi không cần phải chuyển đổi những con số lớn như vậy, nhưng dù sao thì tuyệt vời! +1 – Jay

+1

Tôi gặp phải sự cố trong đó tôi cần phải hoạt động với số lượng lớn và sau khi tìm kiếm trên stackoverflow để giải pháp cuối cùng đã viết mã của riêng tôi :) – inscaven

2

Hãy thử »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

Trong khi mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung liên quan đến ** cách ** và * * tại sao ** nó giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời. – Alexander

Các vấn đề liên quan