Algum módulo Python padrão contém uma função para calcular o inverso multiplicativo modular de um número, ou seja, um número y = invmod(x, p)
assim x*y == 1 (mod p)
? O Google não parece dar boas dicas sobre isso.
Claro, pode-se inventar um algoritmo euclidiano estendido de 10 linhas feito em casa , mas por que reinventar a roda?
Por exemplo, o método Java BigInteger
tem modInverse
. O Python não tem algo semelhante?
pow
função para isso:y = pow(x, -1, p)
. Consulte bugs.python.org/issue36027 . Demorou apenas 8,5 anos desde a pergunta feita até que uma solução aparecesse na biblioteca padrão!Respostas:
Talvez alguém ache isso útil (dos wikibooks ):
fonte
sympy
, entãox, _, g = sympy.numbers.igcdex(a, m)
faz o truque.Se o seu módulo for primo (você o chama
p
), você pode simplesmente calcular:Ou em Python adequado:
Aqui está alguém que implementou alguns recursos de teoria dos números em Python: http://www.math.umbc.edu/~campbell/Computers/Python/numbthy.html
Aqui está um exemplo feito no prompt:
fonte
Você também pode querer dar uma olhada no módulo gmpy . É uma interface entre o Python e a biblioteca de precisão múltipla GMP. gmpy fornece uma função invert que faz exatamente o que você precisa:
Resposta atualizada
Conforme observado por @hyh, o
gmpy.invert()
retorna 0 se o inverso não existe. Isso corresponde ao comportamento dampz_invert()
função GMP .gmpy.divm(a, b, m)
fornece uma solução geral paraa=bx (mod m)
.divm()
retornará uma solução quandogcd(b,m) == 1
e levanta uma exceção quando o inverso multiplicativo não existe.Aviso: Sou o mantenedor atual da biblioteca gmpy.
Resposta atualizada 2
O gmpy2 agora gera uma exceção corretamente quando o inverso não existe:
fonte
gmpy.invert(0,5) = mpz(0)
vez de levantar um erro ...gmpy
pacote? (ou seja, alguma função que tem o mesmo valor, mas é mais rápida do que(a * b)% p
?)(a * b) % p
em uma função não é mais rápida do que apenas avaliar(a * b) % p
em Python. A sobrecarga de uma chamada de função é maior do que o custo de avaliar a expressão. Consulte code.google.com/p/gmpy/issues/detail?id=61 para obter mais detalhes.A partir de 3.8 pythons, a função pow () pode receber um módulo e um número inteiro negativo. Veja aqui . O caso deles de como usá-lo é
fonte
Aqui está um one-liner para CodeFights ; é uma das soluções mais curtas:
Ele retornará
-1
seA
não houver inverso multiplicativo emn
.Uso:
A solução usa o Algoritmo Euclidiano Estendido .
fonte
Sympy , um módulo python para matemática simbólica, tem uma função inversa modular integrada se você não quiser implementar a sua própria (ou se já estiver usando Sympy):
Isso não parece estar documentado no site da Sympy, mas aqui está a docstring: Sympy mod_inverse docstring no Github
fonte
Aqui está o meu código, pode ser desleixado, mas parece funcionar para mim de qualquer maneira.
fonte
O código acima não será executado em python3 e é menos eficiente em comparação com as variantes GCD. No entanto, esse código é muito transparente. Isso me levou a criar uma versão mais compacta:
fonte
n == 7
. Mas por outro lado, é equivalente a este "algoritmo":for i in range(2, n): if i * a % n == 1: return i
Aqui está um 1-liner conciso que faz isso, sem usar nenhuma biblioteca externa.
Observe que isso é realmente apenas egcd, simplificado para retornar apenas o único coeficiente de interesse.
fonte
Para descobrir o inverso multiplicativo modular, eu recomendo usar o Algoritmo Euclidiano Estendido como este:
fonte
a = prevX - quotient * X
deveria serX = prevX - quotient * X
e deveria retornarprevX
. FWIW, esta implementação é semelhante àquela no link de Qaz no comentário à resposta de Märt Bakhoff.Tento soluções diferentes deste tópico e no final uso esta:
Modular_inverse em Python
fonte
return
no egcd está indendido de forma erradaBem, eu não tenho uma função em python, mas tenho uma função em C que você pode facilmente converter para python, na função c abaixo, o algoritmo euclidiano estendido é usado para calcular o mod inverso.
Função Python
A referência à função C acima é obtida do seguinte programa C do link para encontrar o inverso multiplicativo modular de dois números primos relativamente
fonte
do código-fonte de implementação cpython :
de acordo com o comentário acima deste código, ele pode retornar pequenos valores negativos, então você pode verificar se é negativo e adicionar n quando negativo antes de retornar b.
fonte
Muitos dos links acima estão quebrados em 23/01/2017. Encontrei esta implementação: https://courses.csail.mit.edu/6.857/2016/files/ffield.py
fonte