Як перетворити рядок або ціле число в бінарне в Ruby?


168

Як ви створюєте цілі числа 0..9 та математичні оператори + - * / у бінарних рядках. Наприклад:

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

Чи можна це зробити з Ruby 1.8.6, не використовуючи бібліотеку?


Коли ви говорите, що хочете перетворити математичні оператори у бінарні рядки, що саме ви маєте на увазі? Використовувати представлення ASCII, записане у двійковій формі?
бта

Я думаю, ти хотів зробити популярну генетичну алгоритм? :-)
nemesisfixx

Відповіді:


372

У вас є Integer#to_s(base)і String#to_i(base)доступні вам.

Integer#to_s(base) перетворює десяткове число у рядок, що представляє число в зазначеній базовій частині:

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

при цьому зворотний результат отримується за допомогою String#to_i(base):

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

24
@TomRavenscroft Крім того, ви можете використовувати ("%08b" % int)або ("%08b" % string)повертати фіксовану кількість біт.
занепад

1
Блискучий Майк, блискучий Рубі!
Тамер Шлаш

4
-9.to_s(2) => "-1001"Хтось може це пояснити?
користувач1201917

1
Для тих, хто збентежився кодом @ розпаду, як я, він використовує 'sprintf': apidock.com/ruby/Kernel/sprintf
Тейлор Лісс

@ user1201917 Що з цим? 9знаходиться 1001у бінарному.
предпочтений_анон

41

Я задав подібне запитання . Виходячи з відповіді @sawa , найбільш стислим способом представити ціле число в рядку у двійковому форматі є використання форматів рядків:

"%b" % 245
=> "11110101"

Ви також можете вибрати тривалість подання рядка, що може бути корисно, якщо ви хочете порівнювати двійкові числа фіксованої ширини:

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

6
Я зробив місцевий тест на перетворення цілих чисел у двійковий рядок, але результат показує, що такі коди 245.to_s(2)будуть швидше, ніж"%b" % 245
Green Su

Також це не працює належним чином з негативними значеннями.
alex

21

Підбираючи ідею таблиці пошуку bta, ви можете створити таблицю пошуку з блоком. Значення генеруються при першому зверненні та збереженні для подальшого:

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

Ви б природно використовувати Integer#to_s(2), String#to_i(2)або "%b"в реальній програмі, але, якщо ви зацікавлені в тому , як переклад робіт, цей метод обчислює двійкове подання заданого цілого числа з використанням основних операторів:

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

Щоб перевірити, чи працює він:

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

Якщо ви працюєте лише з однозначними цифрами 0-9, швидше за все швидше створити таблицю пошуку, тому вам не доведеться щоразу викликати функції перетворення.

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"

Індексація в цю хеш-таблицю з використанням цілого чи рядкового представлення числа дасть його двійкове представлення у вигляді рядка.

Якщо вам потрібно, щоб двійкові рядки були певною кількістю цифр довгими (зберігайте первісні нулі), то змініть x.to_s(2)на sprintf "%04b", x(де 4мінімальна кількість цифр для використання).


@ bta - я кодую всі ці символи у двійкові, щоб я міг їх використовувати в генетичному алгоритмі. Мені дуже подобається ідея таблиці пошуку для кодування / декодування, оскільки набір обмежений 0..9 і + - * /
mcmaloney

2

Якщо ви шукаєте клас / метод Ruby, я використав це, і я також включив тести:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.