Conversion de décimal en binaire dans R?



(7)

- originellement ajoutée en tant que modification à la réponse de @JoshuaUlrich, car elle est entièrement un corollaire de son et @ nico; il a suggéré que j'ajoute une réponse séparée car elle introduit un paquet en dehors de son ken--

Puisque la réponse de @ JoshuaUlrich est tellement fonctionnelle (6 fonctions consécutives), je trouve que l'opérateur pipe ( %>% ) de magrittr / tidyverse rend la solution suivante plus élégante:

library(magrittr)

intToBits(12) %>% rev %>% as.integer %>% paste(collapse = '')
# [1] "00000000000000000000000000001100"

Nous pouvons également ajouter un dernier appel as.integer pour tronquer tous les zéros en tête:

intToBits(12) %>% rev %>% as.integer %>% paste(collapse = '') %>% as.integer
# [1] 1100

(notons bien entendu que ceci est de nouveau stocké sous forme d' integer , ce qui signifie que R le considère comme étant 1100 représenté dans la base 10, et non 12 représenté dans la base 2)

Notez que l'approche de @ ramanudle (et des autres, notamment @russellpierce, qui fournit une implémentation C ++) est souvent la norme suggérée dans les langages de bas niveau car elle est assez efficace (et fonctionne pour tout nombre pouvant être stocké dans R, c'est-à-dire pas limité à la plage integer ).

Il convient également de mentionner que l' github.com/wch/r-source/blob/… est remarquablement simple (sauf que je ne connais pas les opérateurs & ou >>= en C)

https://src-bin.com

Quelle serait la manière la plus simple de convertir un nombre en base 2 (dans une chaîne, par exemple 5 serait converti en "0000000000000101" ) dans R? Il y a intToBits , mais il retourne un vecteur de chaînes plutôt qu'une chaîne:

> 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

J'ai essayé d'autres fonctions, mais sans succès:

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

Answer #1

Cette fonction prendra un nombre décimal et retournera la séquence binaire correspondante, soit un vecteur de 1 et de 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)
}

Answer #2

Je pense que vous pouvez utiliser le package R.utils, puis la fonction intToBin ()

>library(R.utils)

>intToBin(12)
[1] "1100"

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


Answer #4

Oh, mais que faire si vous avez un entier de 64 bits tel qu'autorisé par le package bit64? Chaque réponse donnée, autre que celle de @epwalsh, ne fonctionnera pas sur le nombre entier de 64 bits car les éléments internes de R et R. utils basés sur C ne le supportent pas. La solution de @ epwalsh est géniale et fonctionne en R si vous chargez le paquet bit64 en premier, sauf que (en utilisant des boucles) en R est lent (toutes les vitesses sont relatives).

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 

Nous pouvons améliorer cela si nous le compilons ...

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

... mais c'est quand même assez lent. Nous pouvons obtenir beaucoup plus rapidement si nous écrivons nos propres composants internes dans C (ce que j'ai fait ici en empruntant le code de @epwalsh - je ne suis pas un programmeur C, évidemment) ...

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 

`` `


Answer #5

intToBits est limité au maximum 2 ^ 32, mais que faire si nous voulons convertir 1e10 en binaire? Voici la fonction pour convertir des nombres flottants en nombres binaires, en supposant qu’ils sont de grands nombres entiers stockés sous forme 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

Cette fonction commence à perdre des chiffres après 2 ^ 53 = 9.007199e15, mais fonctionne très bien pour des nombres plus petits.

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"

Answer #6
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
}



r  

r