Je dois écrire un programme pour calculer a**b % c
où b
et c
sont tous deux de très grands nombres. Si je viens d'utiliser a**b % c
, c'est vraiment lent. Ensuite, j'ai découvert que la fonction intégrée pow()
peut le faire très rapidement en appelant pow(a, b, c)
.
Je suis curieux de savoir comment Python l'implémente? Ou où pourrais-je trouver le fichier de code source qui implémente cette fonction?
Si a
, b
et c
sont des entiers, l'implémentation peut être rendue plus efficace par exponentiation binaire et en réduisant modulo c
à chaque étape, y compris la première (c'est-à-dire réduire a
modulo c
avant même de commencer). C’est ce que l’implémentation de long_pow()
fait effectivement.
Vous pourriez envisager les deux implémentations suivantes pour calculer rapidement (x ** y) % z
.
En Python:
def pow_mod(x, y, z):
"Calculate (x ** y) % z efficiently."
number = 1
while y:
if y & 1:
number = number * x % z
y >>= 1
x = x * x % z
return number
En C:
#include <stdio.h>
unsigned long pow_mod(unsigned short x, unsigned long y, unsigned short z)
{
unsigned long number = 1;
while (y)
{
if (y & 1)
number = number * x % z;
y >>= 1;
x = (unsigned long)x * x % z;
}
return number;
}
int main()
{
printf("%d\n", pow_mod(63437, 3935969939, 20628));
return 0;
}
Implémente pow (x, n) en Python
def myPow(x, n):
p = 1
if n<0:
x = 1/x
n = abs(n)
# Exponentiation by Squaring
while n:
if n%2:
p*= x
x*=x
n//=2
return p
Implémente pow (x, n, m) en Python
def myPow(x,n,m):
p = 1
if n<0:
x = 1/x
n = abs(n)
while n:
if n%2:
p*= x%m
x*=x%m
n//=2
return p
Commander ce link pour l'explication
Python utilise les bibliothèques de mathématiques C pour les cas généraux et sa propre logique pour certains de ses concepts (tels que l'infini).
La ligne 1426 de ce fichier montre le code Python qui implémente math.pow, mais en gros, il se résume à appeler la bibliothèque standard C qui possède probablement une version hautement optimisée de cette fonction.
Python peut être assez lent pour les calculs intensifs, mais Psyco peut vous donner un coup de pouce assez rapide, mais il ne sera pas aussi bon que le code C appelant la bibliothèque standard.
Je ne sais pas à propos de python, mais si vous avez besoin de pouvoirs rapides, vous pouvez utiliser l'exponentiation en quadrillant:
http://en.wikipedia.org/wiki/Exponentiation_by_squaring
C'est une méthode récursive simple qui utilise la propriété commutative des exposants.