Les nombres

Les entiers

Type int en Python.

Il existe plusieurs façons d’entrer un entier sous forme litérale

a = 5 # Décimal
a = 0b1001 # binaire
a = 0x23 # hexadécimal

En Python la taille des entiers est illimitée. Par exemple:

print(3**100)
515377520732011331036461129765621272702107522001

Attention, ce n’est plus le cas lorsque l’on utilise des librairies de calcul numérique (comme numpy ou pandas). Dans ce cas, les nombres sont enregistrés sous une taille finie. Par défaut, il s’agit de nombre enregistré avec 64 bits, en tenant compte du signe, les entiers sont alors compris entre \(-2^63\) et \(2^63\) (exclu)

Attention, lorsqu’il y a un débordement (overflow), il n’y a pas d’erreur et le comportement est inattendu.

import numpy as np

a = np.array([3])
a**100
array([-2984622845537545263])

Lorsqu’un nombre est enregistré sous un format de taille finie, il faut s’imaginer qu’il fonctionne comme une calculatrice dont ont aurait caché les premiers chiffres. Nous allons raisonner en décimal, mais dans la réalité ce sont des bits qui sont manipulés.

Si on ne regarde que les trois derniers chiffres (resp. 64 bits) alors les opérations sont faire modulo 1000 (resp. module \(2^64\)). Par exemple \(50 \times 50 = 2500 = 500\). C’est ce que l’on appel un débordement (overflow).

Les nombres négatifs sont enregistré en utilisant une astuce : regardons l’opération (modulo 1000) suivante : \(997 + 3 = 0\). Le nombre 997 est donc le nombre qui lorsqu’on lui rajoute 3 donne 0, c’est donc \(-3\). Cela explique pourquoi dans l’exemple précédent on obtient un nombre négatif.

Les nombres à virgule flottante

Type float. Il existe plusieurs façon d’entrer un entier sous forme litérale : soit en mettant explicitement un . décimal, soit en utilisant le e de la notation scientifique

a = 1234.567
c = 3e8 # ou 3E8 soit 3 fois 10 à la puissance 8

Attention, le comportement d’un nombre à virgule flottante est différent de celui d’un entier, même lorsqu’il représente un entier

a = 3
b = 3. 
print(a**100)
print(b**100)
515377520732011331036461129765621272702107522001
5.153775207320113e+47

Les nombres sont enregistrés en double précision, sur 64 bits. Il sont enregistrés sous la forme \(s\times m \times 2^e\)\(s\) est le signe (\(\pm 1\) sur un bit), \(m\) la mantisse, un nombre entre 0 et 1 sous la forme \(0.xxxxx\) avec en tout 52 bits, et \(e\) l’exposant, un nombre entier signé sur 11 bits (soit entre -1024 et 1023).

Attention, la précision des nombre à virgule flottante est limitée. Elle vaut \(2^{-52}\), soit environ \(10^{-16}\)

a = 3.14
print(a == a + 1E-15)
print(a == a + 1E-16)
False
True

Les nombres complexes

Type complex

Il sont toujours enregistrés sous la forme de deux nombres à virgules flottantes (partie réelle et partie imaginaire). Il faut utiliser le J ou j pour écrire un nombre complexe sous forme litérale

a = 1 + 3j
a = 1.123j

Il faut forcement précéder le j d’un nombre. Le symbole j seul désignant une variable. Notons que si il est possible de placer des chiffres dans le nom d’un variable (par exemple x1), il n’est pas possible de commencer une variable par un chiffre. Par exemple j1 pourra désigner une variable mais pas 1j.

On peut facilement accéder à la partie réelle et imaginaire des nombres complexe, ce sont des attributs du nombre

a = 1 + 3J
print(a.real)
print(a.imag)
1.0
3.0

Opérations sur le nombres

Les opérations sur les nombres sont les suivantes :

  • somme : +

  • produit : *

  • différence ou négation : -

  • division : /

  • division entière : //

  • modulo (reste de la division euclidienne) : % (par exemple 7%2)

  • puissance : ** (par exemple 2**10)

Les booléens et comparaison

Il existe deux valeurs : True et False (attention à la casse).

Les comparaisons se font à l’aide des symboles <, <=, ==, > et >=. Pour savoir si deux valeurs sont différentes, on utilise !=.

Les opérations sont par ordre de priorité : not, and et or.

print(False and False or True)
print(False and (False or True))
True
False

Les opérations and et or effectuent en fait un test conditionnel. L’instruction A and B est interprétée comme B if not A else A, de même A or B équivaut à A if A else B.

from math import sqrt

x = -1
#if sqrt(x)>.2:
#        print('Hello')

if x>0:
    if sqrt(x)>.2:
        print('Hello')
        
if (x>0) and (sqrt(x)>.2):
    print('Hello')
    

Warning

Les symboles & et | sont des opérateurs binaires. Ils réalisent les opérations and et or sur les entiers bit par bit en binaire (par exemple 6 & 5 donne 4). Il ne faut pas les utiliser pour les opérations sur des booléens. Ils ont aussi une priorité sur les comparaisons

#if (x>0) & (sqrt(x)>0):
#    print('Hello')
x = 3

if x==7 & x==3:
    print('Bonjour')
    
if x==7 and x==3:
    print('Hello')
Bonjour

Conclusion : il est préférable de toujours mettre des parenthèses….