Как преобразовать строку или целое число в двоичную в 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"Может кто-нибудь объяснить это?
user1201917

1
Для тех, кто смущен кодом @ decay, таким как я, он использует '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

Также это не работает должным образом с отрицательными значениями.
Алекс

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.