Jak przekonwertować ciąg lub liczbę całkowitą na binarną w Rubim?


168

Jak tworzyć liczby całkowite 0..9 i operatory matematyczne + - * / in do ciągów binarnych. Na przykład:

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

Czy jest sposób na zrobienie tego w Rubim 1.8.6 bez użycia biblioteki?


Kiedy mówisz, że chcesz zamienić operatory matematyczne na ciągi binarne, co dokładnie masz na myśli? Użyj reprezentacji ASCII zapisanej binarnie?
bta

Chyba chciałeś zrobić popularny algorytm genetyczny? :-)
nemesisfixx

Odpowiedzi:


372

Masz Integer#to_s(base)i String#to_i(base)jesteś dostępny.

Integer#to_s(base) konwertuje liczbę dziesiętną na łańcuch reprezentujący liczbę o określonej podstawie:

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

podczas gdy odwrotność uzyskuje się z String#to_i(base):

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

24
@TomRavenscroft Ponadto możesz użyć ("%08b" % int)lub, ("%08b" % string)aby zwrócić stałą liczbę bitów.
rozpad

1
Genialny Mike, genialny Ruby!
Tamer Shlash

4
-9.to_s(2) => "-1001"Czy ktoś może to wyjaśnić?
user1201917

1
Dla tych, którzy są zdezorientowani kodem @ decay, takim jak ja, używa ``
Taylor Liss

@ user1201917 Co w tym złego? 9jest 1001binarny.
preferred_anon

41

Zadałem podobne pytanie . Opierając się na odpowiedzi @sawa , najbardziej zwięzłym sposobem przedstawienia liczby całkowitej w ciągu w formacie binarnym jest użycie programu formatującego ciąg:

"%b" % 245
=> "11110101"

Możesz także wybrać, jak długa ma być reprezentacja ciągu, co może być przydatne, jeśli chcesz porównać liczby binarne o stałej szerokości:

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

6
Zrobiłem lokalny test, aby przekonwertować liczby całkowite na ciąg binarny, ale wynik pokazuje, że kody takie jak 245.to_s(2)będą szybsze niż"%b" % 245
Zielony Nie

Również to nie działa poprawnie z wartościami ujemnymi.
Alex

21

Biorąc pod uwagę pomysł na tabelę przeglądową bta, możesz utworzyć tabelę przeglądową z blokiem. Wartości są generowane, gdy są po raz pierwszy otwierane i przechowywane na później:

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

Można by oczywiście użyć Integer#to_s(2), String#to_i(2)albo "%b"w prawdziwym programem, ale jeśli jesteś zainteresowany w jaki prac tłumaczeniowych, metoda ta oblicza binarną reprezentację dana liczba całkowita przy użyciu podstawowych operatorów:

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

Aby sprawdzić, czy działa:

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

Jeśli pracujesz tylko z pojedynczymi cyframi 0-9, prawdopodobnie szybciej utworzysz tabelę odnośników, więc nie musisz za każdym razem wywoływać funkcji konwersji.

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"

Indeksowanie do tej tablicy skrótów przy użyciu reprezentacji liczby całkowitej lub łańcucha daje jej binarną reprezentację jako ciąg.

Jeśli chcesz, aby ciągi binarne miały określoną liczbę cyfr (zachowaj zera wiodące), zmień x.to_s(2)na sprintf "%04b", x(gdzie 4jest minimalna liczba cyfr do użycia).


@ bta- Koduję wszystkie te znaki w postaci binarnej, aby móc ich użyć w algorytmie genetycznym. Bardzo podoba mi się pomysł tabeli przeglądowej dla kodowania / dekodowania, ponieważ zestaw jest ograniczony do 0..9 i + - * /
mcmaloney

2

Jeśli szukasz klasy / metody Ruby, użyłem tego, a także dołączyłem testy:

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.