Mit Blick auf x86 Assembly von einem Compiler erzeugt, bemerkte ich, dass (vorzeichenlose) Ganzzahl Divisionen manchmal als ganzzahlige Multiplikationen implementiert sind. Diese Optimierungen scheinen der FormFühren Sie Ganzzahldivision mit Multiplikation
value/n => (value * ((0xFFFFFFFF/n) + 1))/0x100000000
Zum Beispiel zu folgen, eine Division durch 9 ausführen:
12345678/9 = (12345678 * 0x1C71C71D)/0x100000000
Eine Division durch 3 verwenden würde Multiplikation mit 0x55555555 + 1
, und so weiter.
Ausnutzen der Tatsache, dass die mul
Anweisung den hohen Teil des Ergebnisses im edx
Register speichert, kann das Endergebnis der Division mit einer einzigen Multiplikation mit einem magischen Wert erhalten werden. (Obwohl diese Optimierung manchmal in Verbindung mit einer bitweisen Verschiebung am Ende verwendet wird.)
Ich hätte gerne einen Einblick, wie das tatsächlich funktioniert. Wann ist dieser Ansatz gültig? Warum muss 1 zu unserer "magischen Zahl" hinzugefügt werden?
Die Konstante, mit der Sie multiplizieren, ist eine Annäherung des Reziproken. Die zufälligen +/- 1 hier und da sind, um sicherzustellen, dass es immer richtig "gerundet" ist. Der Nachweis, dass eine bestimmte Methode korrekt ist, kann entweder mathematisch oder durch Brute-Force-Tests aller Zähler durchgeführt werden. (Für 32-Bit ist das völlig machbar.) – Mysticial
@Mysticial: Das sieht nach einer Antwort auf mich aus. –
@ScottHunter Vielleicht später, wenn ich arbeitslos bin. Ich habe hier nicht die richtigen Werkzeuge, um eine umfassende Antwort zu geben. – Mysticial