Leistungsfrage: Schnellste Möglichkeit, hexadezimales Zeichen in Java in den Zahlenwert zu konvertieren?

8

Ich möchte von char konvertieren, das einen hexadezimalen Wert (in Groß- oder Kleinschreibung) in Byte darstellt, wie

%Vor%

Ich werde diese Methode extrem oft aufrufen, deshalb ist Leistung wichtig. Gibt es einen schnelleren Weg, als eine vorinitialisierte HashMap<Character,Byte> zu verwenden, um den Wert aus zu bekommen?

Antwort

Es scheint, als wäre es ein Tossup zwischen der Verwendung eines Switch-Cases und Jon Skeets Direct Computing-Lösung - die Switch-Case-Lösung scheint sich jedoch leicht auszuweiten. Gregs Array-Methode gewinnt. Hier sind die Leistungsergebnisse (in ms) für 200.000.000 Läufe der verschiedenen Methoden:

%Vor%

Danke Leute!

Benchmark-Methodencode

Hier, JonSkeet, du alter Konkurrent. ; -)

%Vor%     
Epaga 21.10.2008, 06:53
quelle

12 Antworten

15

Ein vorinitialisiertes Array wäre schneller als eine HashMap. Etwas wie das:

%Vor%

Sie sollten diese Methode mit anderen Methoden vergleichen (z. B. Jon Skeet direkte Methode, um festzustellen, welche für Ihre Anwendung am schnellsten sein wird.

    
Greg Hewgill 21.10.2008, 07:07
quelle
13

Eine Hash-Tabelle wäre relativ langsam. Das ist ziemlich schnell:

%Vor%

Eine andere Option wäre, eine switch / case-Anweisung zu versuchen. Ein Array ist möglicherweise in Ordnung, wenn es sich im Cache befindet, aber ein Fehler könnte teuer sein.

    
Jon Skeet 21.10.2008 07:00
quelle
4

Ich erinnere mich nicht, diese Methode vorher gesehen zu haben, aber Mikko Rantanen hat diese Gleichung in einem Kommentar auf die Frage, Code Golf - hex in (rohe) binäre Konvertierung

%Vor%

Ich weiß nicht, wofür es einen Benchmark geben würde (vielleicht kann jemand es zum obigen Benchmark hinzufügen und es ausführen, aber ich schätze, der% bringt die Leistung zum Erliegen) - aber es ist ein ordentlicher, einfacher Einzeiler für Single Zeichen hexadezimal zu dezimal konvertieren. Handles 0-9, A-F, a-f.

    
Adam Davis 28.04.2009 16:33
quelle
4
%Vor%     
pro 18.12.2008 23:10
quelle
3

Die Verwendung eines Arrays sollte am schnellsten sein.

Ein Array könnte die Größe 16, 16 ^ 2, 16 ^ 3, 16 ^ 4 usw. haben.

Die Umwandlung der Zahl in größere Gruppen als eine würde zu einer Leistungssteigerung führen.

Es wird einen schönen Ort geben, an dem es sich lohnt, möglicherweise vierstellig (64k Tisch).

    
pro 21.10.2008 07:41
quelle
2

Character.getNumericValue (char) ist ein anderer Weg:

%Vor%

Druckt 'a- & gt; 10' wie Sie möchten. Ein anderer Benutzer müsste die Effizienz eines statischen Metod-Aufrufs gegenüber einem HashMap-Lookup kommentieren, oder Sie könnten es selbst überprüfen. Es scheint mir jedoch sauberer / lesbarer zu sein.

    
Keeg 21.10.2008 07:02
quelle
2

einfach, aber langsam:

%Vor%

schneller:

%Vor%

Ich werde keinen speziellen Code für "Leistungsprobleme" verwenden. Wenn Sie dies wirklich häufig verwenden, erstellt der JIT kompilierten Code und die Ausführung wird schnell. Halten Sie Ihren Code sauber. Sie können versuchen und einen Performance-Test schreiben, indem Sie die Ausführungszeit mit dem obigen Code und einer speziellen Implementierung vergleichen - ich wette, Sie werden keine wesentlichen Verbesserungen erhalten.

    
Arne Burmeister 21.10.2008 07:41
quelle
2

Ich glaube nicht, dass Sie eine direkte Array-Suche übertreffen können.

%Vor%     
Staale 21.10.2008 08:00
quelle
2

Hier ist meine optimierte Version von Gregs Code. Auf meiner Box ist es marginal schneller - aber wahrscheinlich innerhalb des Rauschens. Es vermeidet die Untergrenzenprüfung und muss keine Subtraktion durchführen. Die Erstellung eines 64K-Arrays und die Vermeidung von entweder -Begrenzungs-Checks verlangsamten das Ganze - aber mit einem solchen Timing ist es praktisch unmöglich, sicher zu sein, was wirklich ist und was Rauschen ist.

%Vor%     
Jon Skeet 21.10.2008 08:16
quelle
2

Es ist erwähnenswert, dass Sie die% Operation in den meisten Ihrer Tests zeitgesteuert ausführen. Diese Operation dauert etwa genauso lange wie einige der anderen Optionen.

%Vor%     
Peter Lawrey 28.04.2009 20:43
quelle
2

Dude, ich bin Mikrocontroller-Programmierer und in dieser kleinen Welt ist Geschwindigkeit wirklich wichtig. Der schnellste Weg, um eine 'ASCII'-Ziffer in ein Byte umzuwandeln (von' A 'nach 0x0A), ist die Verwendung dieses kleinen Stücks Code

%Vor%

Die Magie dieses Befehls ist einfach, wenn Sie in die Tabelle ascii schauen, finden Sie Zahlen, die mit 0x3_ beginnen, und Buchstaben in den Spalten 0x4_ und 0x6_. 1) Wenn Sie "oder" das ankommende Zeichen (Variable "c") mit 0x20 ändern, ändern Sie niemals Zahlen ... aber für Buchstaben werden Sie Großbuchstaben in Kleinbuchstaben umwandeln. Da wir nur nach A..F (a..f) Werten suchen ... sind mir andere egal. 2) jetzt die Magie. Um Subtraktionen zu vermeiden, verwende ich additive Operatoren. die 0xD0 ist die gleiche von -0x30, und 0xA9 ist die gleiche von -'a '+ 10;

Die durch den Vergleich erzeugte Verzweigungsinstruktion ist ziemlich einfach und hat den Overhead von Tabellen-Lookups und weder "mod" noch andere Operatoren genommen!

Viel Spaß ...

    
user2517201 27.07.2013 04:06
quelle
1

Eine Tabelle mit 16-Bit-Werten, in der Sie zwei Ziffern gleichzeitig nachschlagen können, sollte schneller sein als die in anderen Antworten vorgeschlagenen 8-Bit-Werte. Sie würden die Daten doppelt so schnell wiederholen, halb so oft auf das Array zugreifen und auf Kurzschlüsse anstatt auf Bytes zugreifen, was die CPU weniger Aufgaben und mehr bietet.

Die 8-Bit-Werte würden als x[Integer.toHexString(i).charAt[0]] = i für 0 <= i < 256 vorberechnet. Dann würden Sie einfach nach x[c] für jedes char c in der hexadezimalen Zeichenfolge suchen. Wahrscheinlich möchten Sie die Einträge für Groß- und Kleinschreibung jedes Hexadezimalwerts duplizieren.

Eine Tabelle mit 32-Bit-Werten sollte noch schneller sein, je nachdem, wie viel Speicherplatz Sie sich leisten können.

    
EJP 27.07.2013 04:24
quelle

Tags und Links