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?


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

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

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

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

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- 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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.