Como converter uma string ou número inteiro em binário no Ruby?

168

Como você cria números inteiros 0..9 e operadores matemáticos + - * / in para cadeias binárias. Por exemplo:

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

Existe uma maneira de fazer isso com o Ruby 1.8.6 sem usar uma biblioteca?

mcmaloney
fonte
Quando você diz que deseja converter operadores matemáticos em cadeias binárias, o que exatamente você quer dizer? Use a representação ASCII escrita em binário?
bta
Eu acho que você queria fazer a coisa popular Algoritmo Genético? :-)
nemesisfixx 13/03

Respostas:

372

Você tem Integer#to_s(base)e está String#to_i(base)disponível para você.

Integer#to_s(base) converte um número decimal em uma sequência que representa o número na base especificada:

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

enquanto o inverso é obtido com String#to_i(base):

"1001".to_i(2) #=> 9
Mike Woodhouse
fonte
24
@TomRavenscroft Além disso, você pode usar ("%08b" % int)ou ("%08b" % string)retornar um número fixo de bits.
Decay
1
Mike brilhante, Ruby brilhante!
Tamer Shlash
4
-9.to_s(2) => "-1001"Alguém pode explicar isso?
user1201917
1
Para aqueles confundidos pelo código de @ decadência como eu, ele está usando 'sprintf': apidock.com/ruby/Kernel/sprintf
Taylor Liss
@ user1201917 O que há de errado nisso? 9está 1001em binário.
preferred_anon
41

Eu fiz uma pergunta semelhante . Com base na resposta de @sawa , a maneira mais sucinta de representar um número inteiro em uma string em formato binário é usar o formatador de string:

"%b" % 245
=> "11110101"

Você também pode escolher por quanto tempo a representação de sequência será útil, o que pode ser útil se você quiser comparar números binários de largura fixa:

1.upto(10).each { |n| puts "%04b" % n }
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
Alexander
fonte
6
Eu fiz alguns testes local para converter inteiros a cadeia binária, mas o resultado mostra que os códigos como 245.to_s(2)será mais rápido que"%b" % 245
Verde Su
Além disso, isso não funciona corretamente com valores negativos.
22919 alex alex
21

Seguindo a ideia da tabela de pesquisa do bta, é possível criar a tabela de pesquisa com um bloco. Os valores são gerados quando são acessados ​​e armazenados pela primeira vez para mais tarde:

>> 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
fonte
11

Você naturalmente usar Integer#to_s(2), String#to_i(2)ou "%b"em um programa real, mas, se você estiver interessado em como os trabalhos de tradução, este método calcula a representação binária de um determinado inteiro usando operadores básicos:

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

Para verificar se funciona:

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
fonte
4

Se você estiver trabalhando apenas com os dígitos de 0 a 9, provavelmente será mais rápido criar uma tabela de pesquisa, para que você não precise chamar as funções de conversão todas as vezes.

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"

A indexação nessa tabela de hash usando a representação inteira ou a sequência de um número produzirá sua representação binária como uma sequência.

Se você precisar que as seqüências binárias tenham um determinado número de dígitos (mantenha os zeros à esquerda), mude x.to_s(2)para sprintf "%04b", x(onde 4é o número mínimo de dígitos a ser usado).

bta
fonte
@ bta- Estou codificando todos esses caracteres em binários para que eu possa usá-los em um algoritmo genético. Eu realmente gosto da idéia de uma tabela de pesquisa para a codificação / decodificação, já que o conjunto é limitado a 0..9 e + - * /
mcmaloney
2

Se você está procurando uma classe / método Ruby, usei isso e também incluí os testes:

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
fonte