====== Opérateurs ======
===== Opérateurs mathématiques =====
Les opérateurs mathématiques en python se comptent au nombre de sept : addition, soustraction, multiplication, division, reste de la division (modulo), division entière et puissance. La logique voudrait que les trois premiers soient très rapides, mais que la division et les autres soient bien plus lents. Jettons-y un oeil, en testant des nombres entiers, des nombres flottants, et les deux mélangés.
Lorsque le compilateur est capable de déterminer le résultat à l'avance, par exemple en notant directement ''4 / 4'', le résultat est précalculé à la compilation. La variable ''i'' sert ici à forcer le programme à interpréter l'opération.
# nombres entiers
python -m timeit -n 1000000 -r 100 -s "i=4" "i + 4"
1000000 loops, best of 100: 0.0327 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i - 4"
1000000 loops, best of 100: 0.0318 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i * 4"
1000000 loops, best of 100: 0.0318 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i / 4"
1000000 loops, best of 100: 0.0381 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i % 4"
1000000 loops, best of 100: 0.0692 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i // 4"
1000000 loops, best of 100: 0.0697 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i ** 4"
1000000 loops, best of 100: 0.291 usec per loop
# nombres flottants
python -m timeit -n 1000000 -r 100 -s "i=4.0" "i + 4.0"
1000000 loops, best of 100: 0.0335 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4.0" "i - 4.0"
1000000 loops, best of 100: 0.0335 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4.0" "i * 4.0"
1000000 loops, best of 100: 0.0325 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4.0" "i / 4.0"
1000000 loops, best of 100: 0.0335 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4.0" "i % 4.0"
1000000 loops, best of 100: 0.0526 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4.0" "i // 4.0"
1000000 loops, best of 100: 0.112 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4.0" "i ** 4.0"
1000000 loops, best of 100: 0.102 usec per loop
# entiers et flottants
python -m timeit -n 1000000 -r 100 -s "i=4" "i + 4.0"
1000000 loops, best of 100: 0.0841 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i - 4.0"
1000000 loops, best of 100: 0.0819 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i * 4.0"
1000000 loops, best of 100: 0.0829 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i / 4.0"
1000000 loops, best of 100: 0.0837 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i % 4.0"
1000000 loops, best of 100: 0.106 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i // 4.0"
1000000 loops, best of 100: 0.166 usec per loop
python -m timeit -n 1000000 -r 100 -s "i=4" "i ** 4.0"
1000000 loops, best of 100: 0.162 usec per loop
addition = 327
soustraction = 318
multiplication = 318
division= 381
reste = 692
div. entière = 697
puissance = 2910
addition = 335
soustraction = 335
multiplication = 325
division = 335
reste = 526
div. entière = 1120
puissance = 1020
addition = 841
soustraction = 819
multiplication = 829
division = 837
reste = 1060
div. entière = 1660
puissance = 1620
Addition, soustraction, multiplication **et division** vont strictement à la même vitesse.
Le reste de la division (modulo) est à peine un peu plus lent, et la division entière est pareillement rapide sur des nombres entiers. Lorsqu'il y a des nombres flottants en jeu, la division entière et la puissance sont beaucoup plus longs. Et la puissance de nombres entiers crève littéralement le plafond.
Le mélange de types est plus de deux fois plus lent.
La vitesse d'exécution des opérateurs arithmétiques de base est entièrement liée aux optimisations que peut faire le compilateur, et, en bout de chaîne, au processeur qui les execute. Dans d'autres contextes (version de python plus ancienne, système différent, etc.), les résultats pourraient être différents et, par exemple, avaliser l'idée que la division soit beaucoup plus lente que la multiplication, mais ce n'est plus le cas lors de mes derniers essais.
====Incrémentation et addition====
python -m timeit -n 1000000 -r 10 -s "i=0" "i = i+1"
1000000 loops, best of 10: 0.0958 usec per loop
python -m timeit -n 1000000 -r 10 -s "i=0" "i += 1"
1000000 loops, best of 10: 0.0958 usec per loop
addition = 1
incrémentation = 1
Incrémentation et addition sont tout aussi rapides.
Python n'a pas de réelle incrémentation comme ''++'' : les nombres en python étant inalterables, le seul moyen de changer la valeur d'une variable est de lui assigner une autre valeur. Il s'agit donc intrinsèquement de la même opération, le ''+='' étant seulement un raccourci de syntaxe.
Le compilateur produit le même //bytecode// pour les deux :
import dis
def add(i): i = i+1
def inc(i): i += 1
dis.dis(add)
dis.dis(inc)
2 0 LOAD_FAST 0 (i)
3 LOAD_CONST 1 (1)
6 BINARY_ADD
7 STORE_FAST 0 (i)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
3 0 LOAD_FAST 0 (i)
3 LOAD_CONST 1 (1)
6 INPLACE_ADD
7 STORE_FAST 0 (i)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE