Je kunt hier handig gebruiken dat congruentie bewaard blijft bij optelling en vermenigvuldiging. Een getal is te schrijven als som van cijfers vermenigvuldigt met de basis waarin je werkt tot een bepaalde macht verheven:
getal =
som(basisk * cijferk)
Dus kun je ook schrijven:
getal%m =
som((basisk * cijferk))%m
Of:
getal%m =
som((basisk * cijferk)%m)%m)
Of:
getal%m =
som((basisk%m) * (cijferk%m))%m)%m)
(De cijfer
k%m term is natuurlijk zinloos als basis < m)
Dat principe kun je handig in code omzetten:
C:
1
2
3
4
5
6
7
8
9
| const int cijfers[10] = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3 };
const int basis = 10, m = 983;
int k = 10, b = 1, r = 0;
while (--k >= 0)
{
r = (r + cijfers[k]*b)%m;
b = b*basis%m;
}
printf("%d\n", r); |
Je moet nog steeds wel oppassen voor overflow, maar dat risico is alleen afhankelijk van
m (in deze code moet ongeveer
2*m*m nog in een
int passen, wat met een extra modulo terug te brengen is tot
m*m). Als je efficiente code wil schrijven wil je het doen van de modulo-operatie liefst niet elke iteratie uitvoeren, maar dat is een optimalisatie.
pkuppens schreef op donderdag 08 mei 2008 @ 17:42:
Even uitgaand van een character stream als groot getal representatie en een integer modulus, liefst ook nog een beetje beschaafde, als deler, zou ik iets doen als:
code:
1
2
3
4
5
6
7
| m = 0; // initialiseer
while (input)
g = getch(input); // cijfer pakken van input stream
g0= cijfer(g); // naar cijfer 0..9 omzetten en loop afbreken als dat niet zo is
m = (m*10 + g0) % modulus;
end
return (m); |
Dit werkt ook en is misschien nog wel beter.

Enige risico is dat m*10 +g0 niet mag overflowen in de int, dat gaat goed als modulus < maxint - 10.
Ik denk zou denken dat je
modulus < (maxinit - 10)/10 moet hebben, anders gaat het nog mis als bv.
m = modulus - 1.
[
Voor 34% gewijzigd door
Soultaker op 08-05-2008 18:08
]