Wie konvertiere ich eine Zeichenfolge oder Ganzzahl in Ruby in eine Binärdatei?

167

Wie erstellt man ganze Zahlen 0..9 und mathematische Operatoren + - * / in binären Zeichenfolgen? Beispielsweise:

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

Gibt es eine Möglichkeit, dies mit Ruby 1.8.6 ohne Verwendung einer Bibliothek zu tun?

mcmaloney
quelle
Was genau meinen Sie, wenn Sie sagen, dass Sie mathematische Operatoren in binäre Zeichenfolgen konvertieren möchten? Verwenden Sie die binär geschriebene ASCII-Darstellung?
bta
Ich denke du wolltest den beliebten Genetischen Algorithmus machen? :-)
Nemesisfixx

Antworten:

371

Sie haben Integer#to_s(base)und String#to_i(base)stehen Ihnen zur Verfügung.

Integer#to_s(base) konvertiert eine Dezimalzahl in eine Zeichenfolge, die die Zahl in der angegebenen Basis darstellt:

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

während das Gegenteil erhalten wird mit String#to_i(base):

"1001".to_i(2) #=> 9
Mike Woodhouse
quelle
24
@TomRavenscroft Zusätzlich können Sie eine feste Anzahl von Bits verwenden ("%08b" % int)oder ("%08b" % string)zurückgeben.
Zerfall
1
Genialer Mike, brillanter Rubin!
Tamer Shlash
4
-9.to_s(2) => "-1001"Kann das jemand erklären?
user1201917
1
Für diejenigen, die wie ich von @ decays Code verwirrt sind, verwendet er 'sprintf': apidock.com/ruby/Kernel/sprintf
Taylor Liss
@ user1201917 Was ist daran falsch? 9ist 1001binär.
preferred_anon
41

Ich habe eine ähnliche Frage gestellt . Basierend auf der Antwort von @sawa besteht die prägnanteste Möglichkeit, eine Ganzzahl in einer Zeichenfolge im Binärformat darzustellen, darin, den Zeichenfolgenformatierer zu verwenden:

"%b" % 245
=> "11110101"

Sie können auch auswählen, wie lang die Zeichenfolgendarstellung sein soll. Dies kann hilfreich sein, wenn Sie Binärzahlen mit fester Breite vergleichen möchten:

1.upto(10).each { |n| puts "%04b" % n }
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
Alexander
quelle
6
Ich habe einige lokale Tests durchgeführt, um Ganzzahlen in Binärzeichenfolgen umzuwandeln, aber das Ergebnis zeigt, dass Codes wie 245.to_s(2)schneller sein werden als"%b" % 245
Green Su
Auch dies funktioniert bei negativen Werten nicht richtig.
Alex
21

Wenn Sie die Nachschlagetabellenidee von bta aufgreifen, können Sie die Nachschlagetabelle mit einem Block erstellen. Werte werden generiert, wenn sie zum ersten Mal aufgerufen und für später gespeichert werden:

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

Sie würden natürlich verwenden Integer#to_s(2), String#to_i(2)oder "%b"in einem realen Programm, aber, wenn Sie in , wie die Übersetzungsarbeiten interessiert sind, berechnet diese Methode die binäre Darstellung eines gegebenen ganzzahligen Grund Operatoren:

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

So überprüfen Sie, ob es funktioniert:

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

Wenn Sie nur mit den einzelnen Ziffern 0-9 arbeiten, ist es wahrscheinlich schneller, eine Nachschlagetabelle zu erstellen, sodass Sie die Konvertierungsfunktionen nicht jedes Mal aufrufen müssen.

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"

Die Indizierung in diese Hash-Tabelle unter Verwendung der Ganzzahl- oder Zeichenfolgendarstellung einer Zahl ergibt die Binärdarstellung als Zeichenfolge.

Wenn die binären Zeichenfolgen eine bestimmte Anzahl von Stellen lang sein müssen (führende Nullen beibehalten), wechseln Sie x.to_s(2)zu sprintf "%04b", x(wobei 4die Mindestanzahl der zu verwendenden Stellen ist).

bta
quelle
@ bta- Ich codiere alle diese Zeichen in Binärzeichen, damit ich sie in einem genetischen Algorithmus verwenden kann. Ich mag die Idee einer Nachschlagetabelle für die Codierung / Decodierung sehr, da die Menge auf 0..9 und + - * /
mcmaloney
2

Wenn Sie nach einer Ruby-Klasse / -Methode suchen, habe ich diese verwendet und auch die Tests aufgenommen:

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
quelle