Non sto chiedendo come funziona il concetto matematico del modulo, o come 20 % 3 == 2
capisco bene. Sono più curioso di come il compilatore / interprete lo determini. Posso pensare ad un modo ingenuo molto per farlo, in questo modo:
int modulus(int a, int b)
{
while (a > b)
{
a -= b;
}
return a;
}
(ovviamente questo ha bisogno di un paio di casi in più perché a può essere più piccolo di b, ma si ottiene l'idea.) Ma questo avrebbe alcuni problemi di prestazioni gravi. Ho buttato insieme qualche C ++ per testare l'efficienza sia dell'operatore modulo che della mia funzione ingenua.
#include <iostream>
#include <chrono>
#include <limits>
#include "chrono_io"
using namespace std;
typedef chrono::high_resolution_clock Clock;
int mod(int a, int b)
{
while (a > b)
{
a -= b;
}
return a;
}
int main()
{
auto start = Clock::now();
cout << 20 % 3 << endl;
auto end = Clock::now();
cout << "Modulus on a small number took " << end - start << " seconds to calculate.\n";
start = Clock::now();
cout << numeric_limits<int>::max() % 3 << endl;
end = Clock::now();
cout << "Modulus on a large number took " << end - start << " seconds to calculate.\n";
start = Clock::now();
cout << mod(20, 3) << endl;
end = Clock::now();
cout << "My modulus function on a small number took " << end - start << " seconds to calculate.\n";
start = Clock::now();
cout << mod(numeric_limits<int>::max(), 3) << endl;
end = Clock::now();
cout << "My modulus function on a large number took " << end - start << " seconds to calculate.\n";
}
e l'output è:
2
Modulus on a small number took 43629 nanoseconds seconds to calculate.
1
Modulus on a large number took 5644 nanoseconds seconds to calculate.
2
My modulus function on a small number took 3682 nanoseconds seconds to calculate.
1
My modulus function on a large number took 2153824554 nanoseconds seconds to calculate.
L'operatore del modulo variava da 4.000 a 70.000 nanosecondi. La mia funzione ha sempre vinto sui numeri piccoli, ma ha impiegato circa 2 secondi per il numero elevato. Dato che l'operatore modulo è molto più coerente, presumo che confronta il numero a livello di bit.
Quindi come fa l'operatore del modulo funziona? Posso pensare ad alcuni casi che sarebbero molto facili da determinare. Ad esempio, con mod 2, puoi solo guardare all'ultimo byte. Oppure con mod 4 puoi guardare il penultimo byte. Ma non tutti i numeri hanno un modello così semplice.