2010-02-26 27 views
138

Cómo se crean enteros 0..9 y operadores matemáticos + - */in en cadenas binarias. Por ejemplo:¿Cómo convertir una cadena o entero a binario en Ruby?

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

¿Hay una manera de hacer esto con Ruby 1.8.6 sin necesidad de utilizar una biblioteca?

+0

Cuando dice que quiere convertir operadores matemáticos en cadenas binarias, ¿qué quiere decir exactamente? Use la representación ASCII escrita en binario? – bta

+0

Supongo que querías hacer el popular algoritmo genético. :-) – nemesisfixx

Respuesta

296

Usted tiene Integer#to_s(base) y String#to_i(base) a su disposición.

Integer#to_s(base) convierte un número decimal a una cadena que representa el número en la base especificada:

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

mientras se obtiene la inversa con String#to_i(base):

"1001".to_i(2) #=> 9 
+1

¡Esto me salvó el día! –

+17

@TomRavenscroft Además, puede usar '("% 08b "% int)' o '("% 08b "% string)' para devolver un número fijo de bits. – decay

+1

Brilliant Mike, Brilliant Ruby! –

4

Si sólo está trabajando con el de un solo dígito 0-9, es más rápido crear una tabla de búsqueda para que no tenga que llamar a las funciones de conversión cada vez.

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" 

Indexing en esta tabla hash usando ya sea el número entero o representación de cadena de un número dará su representación binaria como una cadena.

Si requiere las cadenas binarias que tener un cierto número de dígitos de largo (mantener ceros a la izquierda), y luego cambiar a x.to_s(2)sprintf "%04b", x (donde 4 es el número mínimo de dígitos para usar).

+0

@ bta: estoy codificando todos estos caracteres en binario para poder usarlos en un algoritmo genético. Me gusta mucho la idea de una tabla de búsqueda para la codificación/decodificación ya que el conjunto está limitado a 0..9 y + - */ – mcmaloney

19

Retomando la idea tabla de búsqueda de BTA, puede crear la tabla de búsqueda con un bloque. Valores consiguen generan cuando se accede a ellos y se almacenan primero para después:

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

si usted está buscando para una clase/método de Rubí He utilizado este, y también han incluido las pruebas:

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 
8

Usted naturalmente utilizar Integer#to_s(2), String#to_i(2) o "%b" en un programa real, pero, si usted está interesado en cómo funciona la traducción, este método calcula la representación binaria de un número entero dado 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 comprobar 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 
32

me preguntó a similar question. Sobre la base de @sawa 's respuesta, la forma más sucinta para representar un entero en una cadena en formato binario es utilizar el formateador cadena:

"%b" % 245 
=> "11110101" 

También puede elegir el tiempo que la representación de cadena que sea, lo que podría ser útil si quiere comparar números binarios de ancho fijo:

1.upto(10).each { |n| puts "%04b" % n } 
0001 
0010 
0011 
0100 
0101 
0110 
0111 
1000 
1001 
1010 
+6

Hice algunas pruebas locales para convertir números enteros a cadenas binarias, pero el resultado muestra códigos como ' 245.to_s (2) 'será más rápido que' "% b"% 245' –

Cuestiones relacionadas