วิธีการแปลงสตริงหรือเลขจำนวนเต็มเป็นเลขฐานสองใน Ruby


168

คุณจะสร้างจำนวนเต็ม 0..9 และตัวดำเนินการทางคณิตศาสตร์ได้อย่างไร + - * / ในกับสตริงไบนารี ตัวอย่างเช่น:

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

มีวิธีการทำสิ่งนี้กับ Ruby 1.8.6 โดยไม่ต้องใช้ไลบรารีหรือไม่?


เมื่อคุณบอกว่าคุณต้องการแปลงตัวดำเนินการทางคณิตศาสตร์เป็นสตริงไบนารี่คุณหมายถึงอะไรกันแน่? ใช้การแทน ASCII ที่เขียนด้วยเลขฐานสอง?
bta

ฉันคิดว่าคุณอยากจะทำสิ่งที่เป็นที่นิยมทางพันธุกรรมอัลกอริทึม? :-)
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
Brilliant Mike, Brilliant Ruby!
Tamer Shlash

4
-9.to_s(2) => "-1001"มีคนอธิบายเรื่องนี้ได้ไหม
user1201917

1
สำหรับผู้ที่สับสนด้วยรหัสของ @ decay อย่างฉันเขาใช้ 'sprintf': apidock.com/ruby/Kernel/sprintf
Taylor Liss

@ user1201917 เกิดอะไรขึ้นกับสิ่งนี้? 9อยู่1001ในไบนารี
Preferred_anon

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.