Làm cách nào để chuyển đổi một chuỗi hoặc số nguyên thành nhị phân trong Ruby?


167

Làm thế nào để bạn tạo số nguyên 0..9 và toán tử toán học + - * / trong chuỗi nhị phân. Ví dụ:

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

Có cách nào để làm điều này với Ruby 1.8.6 mà không cần sử dụng thư viện không?


Khi bạn nói rằng bạn muốn chuyển đổi toán tử toán học thành chuỗi nhị phân, ý nghĩa chính xác của bạn là gì? Sử dụng biểu diễn ASCII được viết bằng nhị phân?
bta

Tôi đoán bạn muốn làm điều thuật toán di truyền phổ biến? :-)
nemeisfixx

Câu trả lời:


371

Bạn có Integer#to_s(base)String#to_i(base)có sẵn cho bạn.

Integer#to_s(base) chuyển đổi một số thập phân thành một chuỗi đại diện cho số trong cơ sở được chỉ định:

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

trong khi ngược lại thu được với String#to_i(base):

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

24
@TomRavenscroft Ngoài ra, bạn có thể sử dụng ("%08b" % int)hoặc ("%08b" % string)trả về một số bit cố định.
phân rã

1
Rực rỡ Mike, Rực rỡ Ruby!
Tamer Shlash

4
-9.to_s(2) => "-1001"Ai đó có thể giải thích điều này?
dùng1201917

1
Đối với những người bị nhầm lẫn bởi mã của @ decay như tôi, anh ta đang sử dụng 'sprintf': apidock.com/ruby/Kernel/sprintf
Taylor Liss

@ user1201917 Có gì sai với điều đó? 91001trong nhị phân.
preferred_anon

41

Tôi đã hỏi một câu hỏi tương tự . Dựa trên câu trả lời của @sawa , cách ngắn gọn nhất để biểu diễn một số nguyên trong một chuỗi ở định dạng nhị phân là sử dụng trình định dạng chuỗi:

"%b" % 245
=> "11110101"

Bạn cũng có thể chọn thời gian biểu diễn chuỗi là bao lâu, điều này có thể hữu ích nếu bạn muốn so sánh các số nhị phân có chiều rộng cố định:

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

6
Tôi đã thực hiện một số thử nghiệm cục bộ để chuyển đổi số nguyên thành chuỗi nhị phân, nhưng kết quả cho thấy các mã như 245.to_s(2)sẽ nhanh hơn"%b" % 245
Green Su

Ngoài ra, điều này không hoạt động đúng với các giá trị âm.
alex

21

Chọn ý tưởng bảng tra cứu của bta, bạn có thể tạo bảng tra cứu với một khối. Các giá trị được tạo khi chúng được truy cập lần đầu và được lưu trữ sau này:

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

Bạn tự nhiên sẽ sử dụng Integer#to_s(2), String#to_i(2)hoặc "%b"trong một chương trình thực tế, nhưng, nếu bạn đang quan tâm đến cách thức hoạt động dịch thuật, phương pháp này tính toán biểu diễn nhị phân của một số nguyên cho các nhà khai thác sử dụng cơ bản:

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

Để kiểm tra nó hoạt động:

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

Nếu bạn chỉ làm việc với các chữ số duy nhất 0-9, có thể nhanh hơn để tạo bảng tra cứu để bạn không phải gọi các hàm chuyển đổi mỗi lần.

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"

Lập chỉ mục vào bảng băm này bằng cách sử dụng biểu diễn số nguyên hoặc chuỗi của một số sẽ mang lại biểu diễn nhị phân của nó dưới dạng chuỗi.

Nếu bạn yêu cầu các chuỗi nhị phân phải dài một số chữ số nhất định (giữ các số 0 đứng đầu), sau đó đổi x.to_s(2)thành sprintf "%04b", x(trong đó 4số chữ số tối thiểu sẽ sử dụng).


@ bta- Tôi đang mã hóa tất cả các ký tự này thành nhị phân để tôi có thể sử dụng chúng trong thuật toán di truyền. Tôi thực sự thích ý tưởng về bảng tra cứu mã hóa / giải mã vì tập hợp được giới hạn ở 0..9 và + - * /
mcmaloney

2

Nếu bạn đang tìm kiếm một lớp / phương thức Ruby tôi đã sử dụng, và tôi cũng đã bao gồm các bài kiểm tra:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.