2010-02-26 89 views
138

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

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

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

+0

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

+0

Tôi đoán bạn muốn thực hiện thuật toán Di truyền học phổ biến? :-) – nemesisfixx

Trả lời

296

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

Integer#to_s(base) chuyển đổi số thập phân sang một chuỗi đại diện cho số tại các cơ sở quy đị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 
+1

Điều này đã cứu ngày của tôi! –

+17

@TomRavenscroft Ngoài ra, bạn có thể sử dụng '("% 08b "% int)' hoặc '("% 08b "% chuỗi)' để trả về số bit cố định. – decay

+1

Brilliant Mike, Brilliant Ruby! –

4

Nếu bạn chỉ làm việc với các chữ số đơn 0-9, có khả năng nhanh hơn để xây dựng bảng tra cứu, do đó bạn không phải gọi 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 số nguyên hoặc biểu diễn chuỗi của một số sẽ biểu diễn nhị phân dưới dạng chuỗi.

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

+0

@ bta- Tôi 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 của một 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

19

Chọn lên ý tưởng bảng tra cứu của bta, bạn có thể tạo bảng tra cứu bằng một khối. Giá trị được tạo ra khi họ lần đầu tiên được truy cập và lưu trữ cho 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"} 
2

Nếu bạn đang tìm kiếm một Ruby lớp/phương pháp tôi đã sử dụng này, 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 
8

Bạn sẽ tự nhiên sử dụng Integer#to_s(2), String#to_i(2) hoặc "%b" trong chương trình thực, nhưng nếu bạn quan tâm đến cách dịch hoạt động, phương pháp này sẽ tính toán biểu diễn nhị phân của một số nguyên nhất định sử dụng toán tử 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 xem 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 
32

Tôi hỏi a similar question. Dựa trên @sawa 's câu trả lời, cách cô đọng nhất để đại diện cho một số nguyên trong một chuỗi trong định dạng nhị phân là sử dụng định dạng chuỗi:

"%b" % 245 
=> "11110101" 

Bạn cũng có thể chọn cách dài chuỗi đại diện được, mà có thể được 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ử 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' –

Các vấn đề liên quan