Patrząc na zestaw x86 produkowany przez kompilator, zauważyłem, że (bez podpisu) podziały liczby całkowitej są czasem implementowane jako multiplikacje całkowite. Te optymalizacji wydaje podążał za kształtemWykonaj podział całkowity za pomocą mnożenia
value/n => (value * ((0xFFFFFFFF/n) + 1))/0x100000000
Na przykład, poprzez wykonywanie podziału 9:
12345678/9 = (12345678 * 0x1C71C71D)/0x100000000
dzielenia przez 3 użyłby mnożenie 0x55555555 + 1
, i tak dalej.
wykorzystując fakt, że dyspozycja mul
przechowuje dużą część wyniku w rejestrze edx
końcowy wynik podziału można uzyskać za pomocą jednego mnożenia z magicznej wartości. (Chociaż ta optymalizacja jest czasami używana w połączeniu z przesunięciem bitowym na końcu.)
Chciałbym dowiedzieć się, jak to działa. Kiedy to podejście jest prawidłowe? Dlaczego 1 należy dodać do naszej "magicznej liczby"?
Stała, którą mnożymy przez jest przybliżeniem odwrotności. Przypadkowe +/- 1 tu i tam mają zapewnić, że jest to zawsze "zaokrąglone" poprawnie. Udowodnienie, że dana metoda jest prawidłowa, może być wykonane matematycznie lub przez brutalne badanie wszystkich liczników. (Dla wersji 32-bitowej jest to całkowicie wykonalne.) – Mysticial
@Mysticial: To wygląda na odpowiedź. –
@ScottHunter Może później, gdy nie będę pracować. Nie mam tutaj dość narzędzi, by udzielić wyczerpującej odpowiedzi. – Mysticial