Sappiamo che ad esempio modulo di potenza di due può essere espresso così:
x % 2 inpower n == x & (2 inpower n - 1).
Esempi:
x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7
Che dire del generale non potere di due numeri?
Diciamo:
x% 7 ==?
Sappiamo che ad esempio modulo di potenza di due può essere espresso così:
x % 2 inpower n == x & (2 inpower n - 1).
Esempi:
x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7
Che dire del generale non potere di due numeri?
Diciamo:
x% 7 ==?
Risposte:
Prima di tutto, in realtà non è esatto dirlo
x % 2 == x & 1
Controesempio Semplice: x = -1. In molte lingue, tra cui Java, -1 % 2 == -1. Cioè, %non è necessariamente la tradizionale definizione matematica di modulo. Java lo chiama "operatore resto", per esempio.
Per quanto riguarda l'ottimizzazione bit per bit, solo le potenze modulo di due possono essere "facilmente" eseguite in aritmetica bit per bit. In generale, solo le potenze modulo di base b possono essere "facilmente" eseguite con la rappresentazione dei numeri in base b .
In base 10, ad esempio, per non negativo N, N mod 10^ksi prendono solo le kcifre meno significative .
-1 = -1 (mod 2), non sei sicuro di cosa stai ottenendo - vuoi dire che non è lo stesso del resto IEEE 754?
(a / b) / b + a % b == a, per gli operatori di tipo C, aeb interi, b diverso da zero, e anche quello abs(a % b) < abs(b)con le stesse condizioni.
(a / b)* b + a % b == a.
C'è solo un modo semplice per trovare il modulo di 2 ^ i numeri usando bit per bit.
Esiste un modo ingegnoso per risolvere i casi di Mersenne in base al collegamento come n% 3, n% 7 ... Esistono casi speciali per n% 5, n% 255 e casi compositi come n% 6.
Per i casi 2 ^ i, (2, 4, 8, 16 ...)
n % 2^i = n & (2^i - 1)
Quelle più complicate sono difficili da spiegare. Leggi solo se sei molto curioso.
Questo funziona solo per potenze di due (e spesso solo quelle positive) perché hanno la proprietà unica di avere un solo bit impostato su "1" nella loro rappresentazione binaria. Poiché nessun'altra classe di numeri condivide questa proprietà, non è possibile creare espressioni bit per bit per la maggior parte delle espressioni di modulo.
Esistono moduli diversi dalle potenze 2 per i quali esistono algoritmi efficienti.
Ad esempio, se x è 32 bit senza segno int, x% 3 = popcnt (x & 0x55555555) - popcnt (x & 0xaaaaaaaa)
Modulo "7" senza operatore "%"
int a = x % 7;
int a = (x + x / 7) & 7;
Non usando l'operatore bit a bit and ( &) in binario, non c'è. Schizzo di prova:
Supponiamo che ci fosse un valore k tale che x & k == x % (k + 1), ma k! = 2 ^ n - 1 . Allora se x == k , l'espressione x & ksembra "funzionare correttamente" e il risultato è k . Consideriamo ora x == ki : se ci fossero dei bit "0" in k , ci sarebbe qualche i maggiore di 0 che ki può essere espresso solo con 1 bit in quelle posizioni. (Ad esempio, 1011 (11) deve diventare 0111 (7) quando gli è stato sottratto 100 (4), in questo caso il bit 000 diventa 100 quando i = 4. ) Se un bit dell'espressione di k deve cambiare da zero a uno per rappresentare il ki, quindi non può calcolare correttamente x% (k + 1) , che in questo caso dovrebbe essere ki , ma non c'è modo per bit a bit booleano e per produrre quel valore data la maschera.
In questo caso specifico (mod 7), possiamo ancora sostituire% 7 con operatori bit per bit:
// Return X%7 for X >= 0.
int mod7(int x)
{
while (x > 7) x = (x&7) + (x>>3);
return (x == 7)?0:x;
}
Funziona perché 8% 7 = 1. Ovviamente, questo codice è probabilmente meno efficiente di un semplice x% 7, e sicuramente meno leggibile.
Utilizzando bitwise_and, bitwise_or e bitwise_not è possibile modificare qualsiasi configurazione di bit in altre configurazioni di bit (ovvero, questi set di operatori sono "funzionalmente completi"). Tuttavia, per operazioni come il modulo, la formula generale sarebbe necessariamente piuttosto complicata, non mi preoccuperei nemmeno di provare a ricrearla.