Java ne disposant pas d'un opérateur d'exponentiation entière, il faut programmer cette opération (dans le cas des nombres flottants, utiliser Math.exp()). Le programme suivant calcule xe, pour des entiers x et e avec , en accumulant (par multiplication) xdans y, ceci e fois, l'expression y*xe étant un invariant de boucle :
static int exp(int x, int e) { int y = 1; while (e != 0) { y = y*x; e = e-1; } return y; }
Chaque itération effectue une transformation
; par
exemple, le calcul de exp(5,8) effectue les transformations
successives suivantes de (y,e) :
private static int exp_aux(int x, int y, int e) { if (e == 0) { return y; } else { return exp_aux(x, y*x, e-1); } } static int exp(int x, int e) { return exp_aux(x,1,e); }
La fonction exp_aux
est une fonction auxiliaire qui ne sera
appelée que par exp
; c'est pourquoi elle est déclarée
private.
Pour les trois programmes précédents, le nombre d'itérations ou d'appels
récursifs est l'entier e. Il est possible d'accélérer
significativement ce calcul en ramenant ce nombre de e à au plus
,
grâce à la propriété suivante :
private static int exp_fastrec_aux(int x, int y, int e) { if (e == 0) { return y; } else if (e % 2 == 1) { return exp_fastrec_aux(x, x*y, e-1); } else { return exp_fastrec_aux(x*x, y, e/2); } }
La version itérative s'écrit facilement à partir de cette version récursive terminale, en remplaçant la liste des arguments des appels récursifs par des affectations appropriées :
static int exp_fastiter(int x, int e) { int y = 1; while (e!=0) { if (e%2 == 1) { y = x*y; e = e-1; } else { x = x*x; e = e/2; } } return y; }
Le cas bénéficiant de la plus forte accélération est celui où l'exposant
est une puissance de 2 ; voici la suite des transformations de (x,y,e)pour le calcul de 58 (en trois itérations au lieu de 8):