Подтвердить что ты не робот

Преобразование десятичного в двоичный в R?

Каким будет самый простой способ преобразования числа в базу 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"
4b9b3361

Ответ 1

Обратите внимание, что 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 = "")

Ответ 2

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

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

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

Ответ 3

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

>library(R.utils)

>intToBin(12)
[1] "1100"

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

Ответ 4

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

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

`` `

Ответ 7

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

Ответ 8

Попробуйте "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

Ответ 9

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

Поскольку ответ @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 рассматривает его как 1100, представленное в базе 10, а не 12, представленное в базе 2)

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

Также стоит отметить, что реализация C intToBits удивительно проста - смотрите https://en.wikipedia.org/wiki/Bitwise_operations_in_C о деталях, которые могут быть незнакомы пользователям, использующим только R

Ответ 10

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
}