Aller au contenu

La fonction puissance, v2⚓︎

On souhaite améliorer la vitesse de calcul de \(a^n\), pour \(a\) flottant et \(n\) entier naturel.

On constate que

  • \(a^{2022} = a^{1011} × a^{1011}\)
  • \(a^{2023} = a^{2022} × a\)

et que de manière générale

  • si \(n\) est pair, \(a^n = a^{n/2} × a^ {n/2}\), avec \(n/2\) qui est bien entier
  • sinon, \(a^n = a^{n-1} × a\)
###

def puissancepy-undv2(a: float, n: int) -> float:bksl-nl "Renvoie a à la puissance n, pour n >= 0"bksl-nl # méthode récursivebksl-nl ...bksl-nlbksl-nlassert puissancepy-undv2(3.0, 0) == 1.0bksl-nlassert puissancepy-undv2(3.0, 1) == 3.0bksl-nlassert puissancepy-undv2(3.0, 4) == 81.0bksl-nlassert puissancepy-undv2(3.0, 5) == 243.0bksl-nlassert puissancepy-undv2(2.0, 10) == 1024.0bksl-nlbksl-nlbksl-nl

Exercice

Donnez une version récursive de puissance_v2 utilisant ce principe.

Indice

On n'oubliera pas le cas de base n = 0.

Réponse
🐍 Script Python
def puissance_v2(a: float, n: int) -> float:
    "Renvoie `a`  à la puissance `n`, pour n >= 0"
    if n == 0:
        # cas de base
        return 1.0
    elif n % 2 == 0:
        # n est pair
        y = puissance_v2(a, n // 2)
        return y * y
    else:
        # n est impair
        return puissance_v2(a, n - 1) * a

Compléxité

Le cout du calcul de puissance_v2(a, n) est inférieur à deux fois le nombre de bits de n.

Voici un exemple d'arbre d'appels récursifs ← site externe de visualisation.

🐍 Console Python
>>> puissance_v2(3.5, 13)
11827271.778198242
Mécanisme
puissance_v2(3.5, 13) = puissance_v2(3.5, 12) × 3.5 =       11827271.778198242
puissance_v2(3.5, 12) = puissance_v2(3.5, 6) au carré =     3379220.5080566406
puissance_v2(3.5, 6)  = puissance_v2(3.5, 3) au carré =     1838.265625
puissance_v2(3.5, 3)  = puissance_v2(3.5, 2) × 3.5 =        42.875
puissance_v2(3.5, 2)  = puissance_v2(3.5, 1) au carré =     12.25
puissance_v2(3.5, 1)  = puissance_v2(3.5, 0) × 3.5 =        3.5
puissance_v2(3.5, 0)  = (réponse directe)                   1.0

On note alors ce cout \(\mathcal O(\log(n))\), ainsi pour tout flottant et tout entier sur 32 bits, il y aura moins de 64 multiplications, ce qui rend cette version bien plus performante que puissance_v1(a, n).