@Neil - Modulo i Binary Są to dość podstawowe operacje, myślę, że są mniej więcej takie same w każdym języku komputerowym.
James Kolpack
1
Jestem trochę zmęczony tym, że nie widzę opublikowanego języka :) Chociaż myślę, że zwykle, jeśli nie podają, zakładam, że oznacza to C ++ lub C. Zastanawiam się, czy to prawda ..
Garet Claborn
1
Tylko dla każdego, kto ma problem ze zrozumieniem tego, zajrzyj na stackoverflow.com/a/13784820/1414639 . Aha, iw JS z V8 uzyskuję bardzo niewielki wzrost wydajności, używając operatorów bitowych.
Bardi Harborow
1
@JamesKolpack Operacja bitowa może być wykonana DUŻO szybciej na CPU niż na modulo. W rzeczywistości typową sztuczką asemblacyjną do wyzerowania rejestru jest XOR (z powodu tego faktu). W dzisiejszych czasach kompilator może być w stanie zoptymalizować modulo potęgi dwóch, ale nie wiem
Kaiser Keister
Odpowiedzi:
70
Po pierwsze, tak naprawdę nie jest to prawdą
x % 2 == x & 1
Proste kontrprzykład: x = -1. W wielu językach, w tym Java -1 % 2 == -1. Oznacza to, że %niekoniecznie jest to tradycyjna matematyczna definicja modulo. Na przykład Java nazywa to „operatorem reszty”.
Jeśli chodzi o optymalizację bitową, tylko potęgi modulo równe dwóm można „łatwo” wykonać w arytmetyce bitowej. Ogólnie mówiąc, tylko potęgi modulo o podstawie b można „łatwo” wykonać z reprezentacją liczb o podstawie b .
W bazie 10, na przykład, dla nieujemnych N, N mod 10^kjest po prostu biorąc najmniej znaczących kcyfr.
@BlueRaja: Jeśli pozwolisz na liczby ujemne, w zasadzie możesz być pewien (zwłaszcza, że nie wspomniano o żadnym języku), że (a / b) / b + a % b == adla operatorów typu C, liczby całkowite a i b, b niezerowe, a także te abs(a % b) < abs(b)z tymi samymi zastrzeżeniami.
David Thornley
1
@DavidThornley - załóżmy, że masz na myśli (a / b)* b + a % b == a.
sfjac
40
Jest tylko prosty sposób na znalezienie modulo 2 ^ i liczb za pomocą bitów.
Istnieje genialny sposób rozwiązywania przypadków Mersenne'a zgodnie z linkiem, takim jak n% 3, n% 7 ... Istnieją specjalne przypadki dla n% 5, n% 255 i przypadki złożone, takie jak n% 6.
W przypadkach 2 ^ i, (2, 4, 8, 16 ...)
n % 2^i = n & (2^i - 1)
Bardziej skomplikowane są trudne do wyjaśnienia. Czytaj tylko, jeśli jesteś bardzo ciekawy.
głosowanie ++; Doskonały link, dzięki za odniesienie. Radzę innym rzucić okiem, warto ją przeczytać, nawet jeśli jest trochę skomplikowana.
varzeak
link jest najlepszą częścią odpowiedzi.
Amit Kumar,
n% 2 ^ i = n & (1 << i - 1)
Kartik Singh
18
Działa to tylko dla potęg dwójki (i często tylko dodatnich), ponieważ mają one unikalną właściwość posiadania tylko jednego bitu ustawionego na „1” w ich binarnej reprezentacji. Ponieważ żadna inna klasa liczb nie ma tej właściwości, nie można tworzyć wyrażeń bitowych i dla większości wyrażeń modułu.
Nie działa dla 10% 2 = 0 (10 + 10/2) i 2 = 15 i 2 = 2, podobnie 10% 6 = 4. (10 + 10/6) i 6 = 11 i 6 = 2
Sriram Murali
10
Dlaczego miałbyś chcieć dzielić, skoro nie chcesz używać modulo? AFAIK, instrukcja dzielenia jest taka sama, jak ta, aby uzyskać resztę.
Horse SMith
2
@SriramMurali To dlatego, że użyłeś parzystego mod, oczywiście to nie zadziała, jest to obejście dla dziwnych, jak powiedział OP.
ylun.ca
3
Nieużywanie bitowych i (& operatora ) w systemie binarnym, nie ma. Szkic dowodu:
Załóżmy, że było wartością K w taki sposób, x & k == x % (k + 1)ale K = 2 ^ n - 1 . Wtedy, jeśli x == k , wyrażenie x & kwydaje się „działać poprawnie”, a wynikiem jest k . Rozważmy teraz x == ki : jeśli w k było jakieś „0” bitów , istnieje i większe od 0, które ki może być wyrażone tylko za pomocą 1-bitów w tych pozycjach. (Np. 1011 (11) musi stać się 0111 (7) po odjęciu od niego 100 (4), w tym przypadku bit 000 staje się 100, gdy i = 4 ). Jeśli bit z wyrażenia k musi zmienić się od zera do jednego, który reprezentuje ki, to nie może poprawnie obliczyć x% (k + 1) , co w tym przypadku powinno być ki , ale nie ma sposobu na bitowe wartości logiczne i uzyskanie tej wartości podanej masce.
Używając bitwise_and, bitwise_or i bitwise_not można modyfikować dowolne konfiguracje bitów na inne konfiguracje bitowe (tj. Te zestawy operatorów są „funkcjonalnie kompletne”). Jednak w przypadku operacji takich jak moduł ogólny wzór byłby z konieczności dość skomplikowany, nawet nie zawracałbym sobie głowy próbą odtworzenia go.
Odpowiedzi:
Po pierwsze, tak naprawdę nie jest to prawdą
Proste kontrprzykład:
x = -1
. W wielu językach, w tym Java-1 % 2 == -1
. Oznacza to, że%
niekoniecznie jest to tradycyjna matematyczna definicja modulo. Na przykład Java nazywa to „operatorem reszty”.Jeśli chodzi o optymalizację bitową, tylko potęgi modulo równe dwóm można „łatwo” wykonać w arytmetyce bitowej. Ogólnie mówiąc, tylko potęgi modulo o podstawie b można „łatwo” wykonać z reprezentacją liczb o podstawie b .
W bazie 10, na przykład, dla nieujemnych
N
,N mod 10^k
jest po prostu biorąc najmniej znaczącychk
cyfr.Bibliografia
źródło
-1 = -1 (mod 2)
, nie jesteś pewien, do czego zmierzasz - masz na myśli to, że to nie to samo, co reszta IEEE 754?(a / b) / b + a % b == a
dla operatorów typu C, liczby całkowite a i b, b niezerowe, a także teabs(a % b) < abs(b)
z tymi samymi zastrzeżeniami.(a / b)
*b + a % b == a
.Jest tylko prosty sposób na znalezienie modulo 2 ^ i liczb za pomocą bitów.
Istnieje genialny sposób rozwiązywania przypadków Mersenne'a zgodnie z linkiem, takim jak n% 3, n% 7 ... Istnieją specjalne przypadki dla n% 5, n% 255 i przypadki złożone, takie jak n% 6.
W przypadkach 2 ^ i, (2, 4, 8, 16 ...)
Bardziej skomplikowane są trudne do wyjaśnienia. Czytaj tylko, jeśli jesteś bardzo ciekawy.
źródło
Działa to tylko dla potęg dwójki (i często tylko dodatnich), ponieważ mają one unikalną właściwość posiadania tylko jednego bitu ustawionego na „1” w ich binarnej reprezentacji. Ponieważ żadna inna klasa liczb nie ma tej właściwości, nie można tworzyć wyrażeń bitowych i dla większości wyrażeń modułu.
źródło
Jest to szczególnie szczególny przypadek, ponieważ komputery reprezentują liczby o podstawie 2. Można to uogólnić:
(liczba) podstawa % podstawa x
jest równy ostatnim x cyfrom podstawy (liczby) .
źródło
Istnieją moduły inne niż potęgi 2, dla których istnieją wydajne algorytmy.
Na przykład, jeśli x to 32 bity bez znaku int, a następnie x% 3 = popcnt (x & 0x55555555) - popcnt (x & 0xaaaaaaaa)
źródło
Modulo „7” bez operatora „%”
źródło
Nieużywanie bitowych i (
&
operatora ) w systemie binarnym, nie ma. Szkic dowodu:Załóżmy, że było wartością K w taki sposób,
x & k == x % (k + 1)
ale K = 2 ^ n - 1 . Wtedy, jeśli x == k , wyrażeniex & k
wydaje się „działać poprawnie”, a wynikiem jest k . Rozważmy teraz x == ki : jeśli w k było jakieś „0” bitów , istnieje i większe od 0, które ki może być wyrażone tylko za pomocą 1-bitów w tych pozycjach. (Np. 1011 (11) musi stać się 0111 (7) po odjęciu od niego 100 (4), w tym przypadku bit 000 staje się 100, gdy i = 4 ). Jeśli bit z wyrażenia k musi zmienić się od zera do jednego, który reprezentuje ki, to nie może poprawnie obliczyć x% (k + 1) , co w tym przypadku powinno być ki , ale nie ma sposobu na bitowe wartości logiczne i uzyskanie tej wartości podanej masce.źródło
W tym konkretnym przypadku (mod 7) nadal możemy zastąpić% 7 operatorami bitowymi:
Działa, ponieważ 8% 7 = 1. Oczywiście ten kod jest prawdopodobnie mniej wydajny niż zwykły x% 7 iz pewnością mniej czytelny.
źródło
Używając bitwise_and, bitwise_or i bitwise_not można modyfikować dowolne konfiguracje bitów na inne konfiguracje bitowe (tj. Te zestawy operatorów są „funkcjonalnie kompletne”). Jednak w przypadku operacji takich jak moduł ogólny wzór byłby z konieczności dość skomplikowany, nawet nie zawracałbym sobie głowy próbą odtworzenia go.
źródło