¿Algún módulo estándar de Python contiene una función para calcular el inverso multiplicativo modular de un número, es decir, un número y = invmod(x, p)
tal que x*y == 1 (mod p)
? Google no parece dar buenas pistas sobre esto.
Por supuesto, uno puede idear 10 líneas caseras de algoritmo euclidiano extendido , pero ¿por qué reinventar la rueda?
Por ejemplo, el método BigInteger
has de Java modInverse
. ¿No tiene Python algo similar?
pow
función de esto:y = pow(x, -1, p)
. Consulte bugs.python.org/issue36027 . ¡Solo pasaron 8.5 años desde que se hizo la pregunta hasta que apareció una solución en la biblioteca estándar!Respuestas:
Quizás alguien encuentre esto útil (de wikilibros ):
fuente
sympy
, entoncesx, _, g = sympy.numbers.igcdex(a, m)
funciona.Si su módulo es primo (lo llama usted
p
), simplemente puede calcular:O en Python propiamente dicho:
Aquí hay alguien que ha implementado algunas capacidades de teoría de números en Python: http://www.math.umbc.edu/~campbell/Computers/Python/numbthy.html
Aquí hay un ejemplo hecho en el indicador:
fuente
Es posible que también desee ver el módulo gmpy . Es una interfaz entre Python y la biblioteca de precisión múltiple GMP. gmpy proporciona una función de inversión que hace exactamente lo que necesita:
Respuesta actualizada
Como señaló @hyh,
gmpy.invert()
devuelve 0 si no existe el inverso. Eso coincide con el comportamiento de lampz_invert()
función de GMP .gmpy.divm(a, b, m)
proporciona una solución general aa=bx (mod m)
.divm()
devolverá una solución cuandogcd(b,m) == 1
y genere una excepción cuando el inverso multiplicativo no exista.Descargo de responsabilidad: soy el mantenedor actual de la biblioteca gmpy.
Respuesta actualizada 2
gmpy2 ahora genera correctamente una excepción cuando la inversa no existe:
fuente
gmpy.invert(0,5) = mpz(0)
lugar de generar un error ...gmpy
paquete? (es decir, alguna función que tiene el mismo valor pero es más rápida que(a * b)% p
?)(a * b) % p
en una función no es más rápido que evaluar(a * b) % p
en Python. La sobrecarga de una llamada a función es mayor que el costo de evaluar la expresión. Consulte code.google.com/p/gmpy/issues/detail?id=61 para obtener más detalles.A partir de 3.8 pitones, la función pow () puede tomar un módulo y un entero negativo. Vea aquí . Su caso de cómo usarlo es
fuente
Aquí hay una sola línea para CodeFights ; es una de las soluciones más cortas:
Volverá
-1
siA
no tiene inverso multiplicativon
.Uso:
La solución utiliza el algoritmo euclidiano extendido .
fuente
Sympy , un módulo de Python para matemáticas simbólicas, tiene una función inversa modular incorporada si no desea implementar la suya propia (o si ya está usando Sympy):
Esto no parece estar documentado en el sitio web de Sympy, pero aquí está la cadena de documentos: Sympy mod_inverse docstring en Github
fuente
Aquí está mi código, puede que sea descuidado, pero parece funcionar para mí de todos modos.
fuente
El código anterior no se ejecutará en python3 y es menos eficiente en comparación con las variantes de GCD. Sin embargo, este código es muy transparente. Me impulsó a crear una versión más compacta:
fuente
n == 7
. Pero de lo contrario, se trata del equivalente de este "algoritmo":for i in range(2, n): if i * a % n == 1: return i
Aquí hay una línea simple concisa que lo hace, sin usar bibliotecas externas.
Tenga en cuenta que esto es realmente solo egcd, optimizado para devolver solo el coeficiente de interés único.
fuente
Para descubrir el inverso multiplicativo modular, recomiendo usar el algoritmo euclidiano extendido como este:
fuente
a = prevX - quotient * X
deberíaX = prevX - quotient * X
haberlo y debería volverprevX
. FWIW, esta implementación es similar a la del enlace de Qaz en el comentario a la respuesta de Märt Bakhoff.Intento diferentes soluciones de este hilo y al final utilizo esta:
Modular_inverse en Python
fuente
return
en egcd se incluye de manera incorrectaBueno, no tengo una función en Python, pero tengo una función en C que puedes convertir fácilmente a Python, en la siguiente función c, el algoritmo euclidiano extendido se usa para calcular la modificación inversa.
Función Python
La referencia a la función C anterior se toma del siguiente enlace del programa C para encontrar el inverso multiplicativo modular de dos números relativamente primos
fuente
del código fuente de implementación de cpython :
de acuerdo con el comentario sobre este código, puede devolver pequeños valores negativos, por lo que podría verificar si es negativo y agregar n cuando sea negativo antes de devolver b.
fuente
Muchos de los enlaces anteriores están rotos a partir del 23/01/2017. Encontré esta implementación: https://courses.csail.mit.edu/6.857/2016/files/ffield.py
fuente