Comment convertir une chaîne ou un entier en binaire en Ruby?

168

Comment créer des entiers 0..9 et des opérateurs mathématiques + - * / dans des chaînes binaires. Par exemple:

 0 = 0000,
 1 = 0001, 
 ...
 9 = 1001

Existe-t-il un moyen de faire cela avec Ruby 1.8.6 sans utiliser de bibliothèque?

mcmaloney
la source
Lorsque vous dites que vous voulez convertir des opérateurs mathématiques en chaînes binaires, que voulez-vous dire exactement? Utiliser la représentation ASCII écrite en binaire?
bta le
Je suppose que vous vouliez faire le truc populaire de l'algorithme génétique? :-)
nemesisfixx

Réponses:

372

Vous avez Integer#to_s(base)et String#to_i(base)à votre disposition.

Integer#to_s(base) convertit un nombre décimal en une chaîne représentant le nombre dans la base spécifiée:

9.to_s(2) #=> "1001"

tandis que l'inverse est obtenu avec String#to_i(base):

"1001".to_i(2) #=> 9
Mike Woodhouse
la source
24
@TomRavenscroft De plus, vous pouvez utiliser ("%08b" % int)ou ("%08b" % string)pour renvoyer un nombre fixe de bits.
désintégration du
1
Brillant Mike, brillant rubis!
Tamer Shlash
4
-9.to_s(2) => "-1001"Quelqu'un peut-il expliquer cela?
user1201917
1
Pour ceux qui sont confus par le code de @ decay comme moi, il utilise ' sprintf
Taylor Liss
@ user1201917 Quel est le problème avec ça? 9est 1001en binaire.
preferred_anon
41

J'ai posé une question similaire . Sur la base de la réponse de @sawa , la manière la plus succincte de représenter un entier dans une chaîne au format binaire est d'utiliser le formateur de chaîne:

"%b" % 245
=> "11110101"

Vous pouvez également choisir la longueur de la représentation sous forme de chaîne, ce qui peut être utile si vous souhaitez comparer des nombres binaires de largeur fixe:

1.upto(10).each { |n| puts "%04b" % n }
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
Alexandre
la source
6
J'ai fait un test local pour convertir des entiers en chaîne binaire, mais le résultat montre que des codes comme 245.to_s(2)seront plus rapides que"%b" % 245
Green Su
De plus, cela ne fonctionne pas correctement avec des valeurs négatives.
alex
21

Reprenant l'idée de table de recherche de bta, vous pouvez créer la table de recherche avec un bloc. Les valeurs sont générées lors de leur premier accès et stockées pour plus tard:

>> lookup_table = Hash.new { |h, i| h[i] = i.to_s(2) }
=> {}
>> lookup_table[1]
=> "1"
>> lookup_table[2]
=> "10"
>> lookup_table[20]
=> "10100"
>> lookup_table[200]
=> "11001000"
>> lookup_table
=> {1=>"1", 200=>"11001000", 2=>"10", 20=>"10100"}
Michael Kohl
la source
11

Vous utiliseriez naturellement Integer#to_s(2), String#to_i(2)ou "%b"dans un programme réel, mais, si vous êtes intéressé par le fonctionnement de la traduction, cette méthode calcule la représentation binaire d'un entier donné à l'aide d'opérateurs de base:

def int_to_binary(x)
  p = 0
  two_p = 0
  output = ""

  while two_p * 2 <= x do
    two_p = 2 ** p
    output << ((two_p & x == two_p) ? "1" : "0")
    p += 1
  end

  #Reverse output to match the endianness of %b
  output.reverse
end

Pour vérifier que cela fonctionne:

1.upto(1000) do |n|
  built_in, custom = ("%b" % n), int_to_binary(n)
  if built_in != custom
    puts "I expected #{built_in} but got #{custom}!"
    exit 1
  end
  puts custom
end
joews
la source
4

Si vous travaillez uniquement avec les chiffres uniques 0-9, il est probablement plus rapide de créer une table de recherche afin que vous n'ayez pas à appeler les fonctions de conversion à chaque fois.

lookup_table = Hash.new
(0..9).each {|x|
    lookup_table[x] = x.to_s(2)
    lookup_table[x.to_s] = x.to_s(2)
}
lookup_table[5]
=> "101"
lookup_table["8"]
=> "1000"

L'indexation dans cette table de hachage à l'aide de la représentation entière ou sous forme de chaîne d'un nombre donnera sa représentation binaire sous forme de chaîne.

Si vous souhaitez que les chaînes binaires comportent un certain nombre de chiffres (conservez les zéros non significatifs), passez x.to_s(2)à sprintf "%04b", x(où 4est le nombre minimum de chiffres à utiliser).

bta
la source
@ bta- J'encode tous ces caractères en binaire pour pouvoir les utiliser dans un algorithme génétique. J'aime beaucoup l'idée d'une table de recherche pour l'encodage / décodage puisque l'ensemble est limité à 0..9 et + - * /
mcmaloney
2

Si vous recherchez une classe / méthode Ruby, j'ai utilisé ceci, et j'ai également inclus les tests:

class Binary
  def self.binary_to_decimal(binary)
    binary_array = binary.to_s.chars.map(&:to_i)
    total = 0

    binary_array.each_with_index do |n, i|
      total += 2 ** (binary_array.length-i-1) * n
    end
    total
   end
end

class BinaryTest < Test::Unit::TestCase
  def test_1
   test1 = Binary.binary_to_decimal(0001)
   assert_equal 1, test1
  end

 def test_8
    test8 = Binary.binary_to_decimal(1000)
    assert_equal 8, test8
 end

 def test_15
    test15 = Binary.binary_to_decimal(1111)
    assert_equal 15, test15
 end

 def test_12341
    test12341 = Binary.binary_to_decimal(11000000110101)
    assert_equal 12341, test12341
 end
end
SharifH
la source