Ruby: die Anzahl der 1 ist eine binäre Zahl,
Habe ich eine binäre Zahl (52 bits) als Zeichenfolge dargestellt "01100011...."
Was wäre der Schnellste Weg, um die Anzahl der 1 ist?
"01100011....".count("1")
offensichtlich funktioniert, ist aber sehr zeitaufwendig, wenn diese Arbeit getan werden muss, um Tausende Male.
ok, ein paar mehr Infos. Ich bin versucht zu erstellen-bit-Vektoren für die Worte wie folgt
def bit_vec(str)
alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
bv = ""
alphabet.each_char do |a|
if str.include?(a)
bv += "1"
else
bv += "0"
end
end
bv
end
Den bit_vec Methode aufgerufen wird, wird über 170K Zeiten. Ich speichern die bit-Vektoren in einer hash-und nutzen Sie, um zu finden, die ähnliche Wörter zu einem gegebenen Wort von XOR ' Ing des bit-Vektoren und zählen der Anzahl von 1 (mehr 1 == weniger ähnlichkeit). Wenn die count-Methode verwenden, die nicht mit String#scan die was anderes nutzen könnte?
Ich weiß, Ruby ist langsamer als beispielsweise C oder Java. Ich bin gerade auf der Suche zur Verbesserung der Algorithmus, die beste, die ich kann. Ich bin nicht auf der Suche für roh-Geschwindigkeit.
Vielleicht ist das enthalten? Methode ist der Engpass?
- Anstelle der bit-Vektoren, könnte ich versuchen, die Speicherung der strings, die als array von Buchstaben und tun so etwas wie dieses (["a", "b", "c"] & ["x","b","x"]).Größe
Du musst angemeldet sein, um einen Kommentar abzugeben.
Beachten Sie, dass das problem der Zählung der 1-bits bezeichnet man als "population count".
Zumindest in Ruby, bleiben Sie bei Umgang mit diesen als string über die
count
Methode, es sei denn, Sie haben einen zwingenden Grund für die Verwendung von Ganzzahlen.count
:Benchmark: 78.60 s für zu 10.000.000 Iterationen (127,225.63 Iterationen pro Sekunde)
Bei integer-math,
Wenn Sie kümmern sich nicht um die oben genannten Werte
2**32
,Benchmark: 105.73 s für zu 10.000.000 Iterationen (94,579.03 Iterationen pro Sekunde)
Wenn Sie kümmern sich um Werte, die über
2**32
,Benchmark: 365.59 s für zu 10.000.000 Iterationen (27,353.27 Iterationen pro Sekunde)
Nachtrag:
Code:
Benchmark: 78.25 s für 1.000.000 Iterationen (12,779.56 Iterationen pro Sekunde)
Diesem code:
Hinweis: Sie sagte, dass Sie es mit einem 52-bit-Zahl, also bin ich davon ausgegangen, dass Sie kümmerte sich um die beiden groß-und Kleinbuchstaben (26 + 26 = 52). Entschied ich mich zu prüfen, für die Großbuchstaben zuerst, weil das ist, wie Sie erscheinen in so ziemlich jeden Zeichensatz immer, die Berechnung ein wenig einfacher.
Benchmark: 24.86 s für 1.000.000 Iterationen (40,231.60 Iterationen pro Sekunde)
3.14 x speed-up.
Sind Sie gehen zu müssen
O(n)
Leistung, egal was. Versuchen Sie, diese einfache ruby-Befehl. Messen, ob es wirklich ein problem.Dieses einfache Skript, gemessen mit
time ruby test.rb
nahm 0.058 CPU-Sekunden. Dies ist auf eine alte 1,25 Ghz Prozessor. Sind Sie wirklich sicher, dass dieser Vorgang zu langsam?Wenn das nicht schnell genug schreiben Sie eine C-Erweiterung. Versuchen Sie zu vermeiden, mit Bedingungen. Schreiben Sie es wie folgt:
Aber ehrlich gesagt, wenn Sie müssen diese Art von Geschwindigkeit ruby ist die falsche Sprache für dich. Es gibt so viele verschiedene Dinge in ruby, die nehmen viel mehr Zeit als eine einfache
.count("1")
..count()
verwendetString#scan
intern. Vielleicht ist dein Flaschenhals woanders ist.vom http://www.bergek.com/2009/03/11/count-number-of-bits-in-a-ruby-integer/
vom http://snippets.dzone.com/posts/show/4233
Hier ist ein post mit verschiedenen Schleifen (in c) für die Zählung der auf die Dichte von 0 vs. 1
http://gurmeetsingh.wordpress.com/2008/08/05/fast-bit-counting-routines/
scan(/1/).size
ist mehr als 10 mal langsamer alscount("1")
.Hier ist ein weiterer benchmark: https://gist.github.com/knugie/3865903
Einfach führen Sie es auf Ihrem Computer, wenn Sie in Zweifel.
Ruby sollte nicht verwendet werden, für die maximale Optimierung, aber die überprüfung für Engpässe in Ihrem code ist immer sinnvoll. Ein Algorithmus, der funktioniert gut in einem Bereich nicht notwendigerweise auch in einem anderen. Versuchen Sie, verwenden Sie echte Daten von Ihrer Anwendung für die Optimierung.
Beispiel-AUSGABE:
Split den string in 8, schauen Sie jeden Eintrag in einer 128-Eintrag lookup-Tabelle und summieren Sie?
Ich weiß.. das ist lächerlich... nur teilen einige Ideen 😉
count
in Rubinrot, fast garantiert.