- Si necesita la solución más rápida y no necesita ser portátil, puede hacerlo con el ensamblador en x86–64 y PPC / Power (y quizás algunos otros). La instrucción mulq para x86–64 hace una multiplicación completa de 64 × 64-> 128, luego divq le da el cociente y el resto. No hay traducción 1: 1 de estos con C, por lo que debe hacerlo con ensamblador. Esto funciona con gcc, clang, MSVC, etc.
- Utilice un tipo intermedio más grande, por ejemplo, uint64_t u uint128_t. Modern GCC y Clang le brindan estos tipos en cualquier plataforma. Boost también te ofrece un tipo de 128 bits. Esto probablemente será más lento que el ASM anterior, pero más rápido que hacerlo usted mismo. Algunos compiladores incluso serán lo suficientemente inteligentes como para convertirlo en el # 1 si es posible.
- Use una biblioteca de multiprecisión como GMP. Probablemente más pesado de lo que necesita.
- Su propio método, por ejemplo, aquí es un ejemplo bastante optimizado (para los accesos directos pequeños a, b, el intercambio a / b puede ahorrar mucho tiempo, ambas rutas evitan mod y se dividen por completo en su bucle, una pequeña optimización para el caso de 63 bits). Para mis pruebas, esto es 10 veces más rápido que las funciones que muestran Tonmoy y Bind. Todavía es más de 10 veces más lento que la solución ASM (no sorprende que dos instrucciones de ensamblaje superen un bucle corto).
estático uint64_t mulmod (uint64_t a, uint64_t b, uint64_t n) {
uint64_t r = 0;
si (a> = n) a% = n; / * Atención cuidadosa de la persona que llama * /
si (b> = n) b% = n; / * debería hacerlos innecesarios. * /
if ((a | b) <(1ULL << 32)) return (a * b)% n;
if (a <b) {uint64_t t = a; a = b; b = t; }
if (n <= (1ULL << 63)) {
mientras que (b> 0) {
si (b & 1) {r + = a; si (r> = n) r – = n; }
b >> = 1;
si (b) {a + = a; si (a> = n) a – = n; }
}
} más {
mientras que (b> 0) {
si (b & 1) r = ((nr)> a)? r + a: r + an; / * r = (r + a)% n * /
b >> = 1;
si (b) a = ((na)> a)? a + a: a + an; / * a = (a + a)% n * /
}
}
volver r;
}
Asegúrese de probar algunas pruebas unitarias. Por ejemplo, lo siguiente:
mulmod(13151668037435042619,15457154184134767374,17762506985585424311)
- ¿Cómo podemos verificar de forma recursiva si una lista vinculada individualmente es un palíndromo?
- ¿Cuál es la última actualización de algo en SEO?
- ¿Qué son los árboles de búsqueda binarios?
- Cómo implementar este algoritmo usando Matlab
- ¿Cuál es la relación entre matrices y matrices variables de programas de computadora?
debe devolver 1599139733680599118
. Un par de otros ejemplos de código en otras respuestas no lo hacen bien, pero probablemente funcionen bien para entradas de 63 bits; ese último bit es complicado. Compare ejemplos con un programa que hace multiprecisión como Pari / GP, Mathematica, Perl con bigint, Python con GMPY, etc.
También puede encontrar código de ejemplo en Wikipedia: Aritmética modular – Wikipedia