Преобразование десятичной в двоичную в R? - PullRequest
31 голосов
/ 07 июля 2011

Какой самый простой способ преобразовать число в основание 2 (в строке, как, например, 5 будет преобразовано в "0000000000000101") в R?Существует 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 ]

24 голосов
/ 07 июля 2011

paste(rev(as.integer(intToBits(12))), collapse="") выполняет работу

paste с параметром collapse сворачивает вектор в строку.Вы должны использовать rev, чтобы получить правильный порядок байтов.

as.integer удаляет лишние нули

19 голосов
/ 07 июля 2011

Обратите внимание, что intToBits() возвращает «сырой» вектор, а не символьный вектор (строки).Обратите внимание, что мой ответ является небольшим расширением @ nico исходного ответа , который удаляет начальный «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 , мы можем использовать as.integer() в качестве более краткого способа удаления начального нуля из каждого бита.

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

Простодля удобства копирования и вставки ниже приведена функциональная версия:

dec2bin <- function(x) paste(as.integer(rev(intToBits(x))), collapse = "")
16 голосов
/ 01 мая 2014

Я думаю, что вы можете использовать пакет R.utils, тогда функция intToBin ()

>library(R.utils)

>intToBin(12)
[1] "1100"

> typeof(intToBin(12))
[1] "character"
8 голосов
/ 23 июня 2015

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"
6 голосов
/ 27 января 2012

Посмотрите на пакет R.utils - там есть функция intToBin ...

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

5 голосов
/ 13 мая 2015

О, но что делать, если у вас есть 64-битное целое число, разрешенное пакетом bit64?Каждый заданный ответ, кроме ответа @epwalsh, не будет работать с 64-битным целым числом, потому что основанные на C внутренние компоненты R и R.utils не поддерживают его.Решение @ epwalsh великолепно и работает в R, если вы сначала загружаете пакет bit64, за исключением того, что он (с использованием циклов) в 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 

```

3 голосов
/ 17 октября 2014

Эта функция будет принимать десятичное число и возвращать соответствующую двоичную последовательность, то есть вектор из 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)
}
2 голосов
/ 13 февраля 2017

Попробуйте »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
1 голос
/ 04 апреля 2018

- первоначально добавлено как правка к ответу @ JoshuaUlrich, так как это полностью следствие его и @ nico's; он предложил добавить отдельный ответ, поскольку он вводит пакет вне его кена -

Поскольку ответ @ JoshuaUlrich является настолько функциональным (6 последовательных функций), я считаю, что оператор pipe (%>%) из 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 рассматривает его как 1100, представленное в базе 10, а не 12, представленное в базе 2)

Обратите внимание, что подход @ ramanudle (и других, особенно @russellpierce, который дает реализацию C ++) часто является стандартом, предлагаемым в низкоуровневых языках, поскольку это довольно эффективный подход (и он работает для любого числа, которое может быть сохранено в R, т. е. не ограничивается integer диапазоном).

Также стоит упомянуть, что реализация C intToBits удивительно проста (за исключением того, что я не знаю операторов & или >>= в C)

0 голосов
/ 11 февраля 2018
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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...