Bagaimana cara mengubah string atau integer ke biner di Ruby?

168

Bagaimana Anda membuat bilangan bulat 0..9 dan operator matematika + - * / in ke string biner. Sebagai contoh:

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

Apakah ada cara untuk melakukan ini dengan Ruby 1.8.6 tanpa menggunakan perpustakaan?

mcmaloney
sumber
Ketika Anda mengatakan ingin mengonversi operator matematika ke string biner, apa sebenarnya yang Anda maksud? Gunakan representasi ASCII yang ditulis dalam biner?
bta
Saya kira Anda ingin melakukan hal Algoritma Genetika populer? :-)
nemesisfixx

Jawaban:

372

Anda memiliki Integer#to_s(base)dan String#to_i(base)tersedia untuk Anda.

Integer#to_s(base) mengonversi angka desimal menjadi string yang mewakili angka dalam basis yang ditentukan:

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

sedangkan kebalikannya diperoleh dengan String#to_i(base):

"1001".to_i(2) #=> 9
Mike Woodhouse
sumber
24
@ TomRavenscroft Selain itu, Anda dapat menggunakan ("%08b" % int)atau ("%08b" % string)untuk mengembalikan jumlah bit yang tetap.
pembusukan
1
Brilliant Mike, Brilliant Ruby!
Tamer Shlash
4
-9.to_s(2) => "-1001"Adakah yang bisa menjelaskan hal ini?
user1201917
1
Bagi mereka yang bingung dengan kode @ decay seperti saya, ia menggunakan 'sprintf': apidock.com/ruby/Kernel/sprintf
Taylor Liss
@ user1201917 Apa yang salah dengan itu? 9adalah 1001dalam biner.
preferred_anon
41

Saya mengajukan pertanyaan serupa . Berdasarkan jawaban @sawa , cara paling ringkas untuk merepresentasikan integer dalam string dalam format biner adalah dengan menggunakan string formatter:

"%b" % 245
=> "11110101"

Anda juga dapat memilih berapa lama representasi string, yang mungkin berguna jika Anda ingin membandingkan angka biner lebar-lebar:

1.upto(10).each { |n| puts "%04b" % n }
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
Alexander
sumber
6
Saya melakukan beberapa tes lokal untuk mengkonversi bilangan bulat ke string biner, tetapi hasilnya menunjukkan bahwa kode seperti 245.to_s(2)akan lebih cepat daripada"%b" % 245
Green Su
Juga ini tidak berfungsi dengan baik dengan nilai negatif.
alex
21

Mengambil ide tabel pencarian bta, Anda dapat membuat tabel pencarian dengan sebuah blok. Nilai-nilai dihasilkan ketika mereka pertama kali diakses dan disimpan untuk nanti:

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

Anda tentu akan menggunakan Integer#to_s(2), String#to_i(2)atau "%b"dalam program nyata, tetapi, jika Anda tertarik pada cara kerja terjemahan, metode ini menghitung representasi biner dari bilangan bulat yang diberikan menggunakan operator dasar:

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

Untuk memeriksanya berfungsi:

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

Jika Anda hanya bekerja dengan satu digit 0-9, kemungkinan lebih cepat untuk membuat tabel pencarian sehingga Anda tidak perlu memanggil fungsi konversi setiap saat.

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"

Pengindeksan ke tabel hash ini menggunakan representasi integer atau string nomor akan menghasilkan representasi biner sebagai string.

Jika Anda membutuhkan string biner untuk menjadi jumlah digit tertentu (tetap memimpin nol), kemudian ubah x.to_s(2)ke sprintf "%04b", x(di mana 4jumlah minimum digit untuk digunakan).

bta
sumber
@ bta- Saya menyandikan semua karakter ini ke dalam biner sehingga saya dapat menggunakannya dalam algoritma genetika. Saya sangat menyukai ide tabel pencarian untuk encode / decode karena set terbatas pada 0,9 dan + - * /
mcmaloney
2

Jika Anda mencari kelas Ruby / metode yang saya gunakan ini, dan saya juga menyertakan tes:

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
sumber