Mathématice, intégration des Tice dans l'enseignement des mathématiques  
Sommaire > N°63 - Janvier 2019 - En cours d’élaboration > L’informatique peut-elle sauver les maths (...)

L’informatique peut-elle sauver les maths ?
Moteur de recherche
Mis en ligne le 7 décembre 2018, par Alain Busser

Cet article est placé sous licence CC-by-SA : Il est permis d’en faire une utilisation commerciale à condition de citer MathemaTICE et de laisser cette licence.

Dans le rapport d’activité de la revue MathemaTICE 17-18, on lit « le progressif déclin des mathématiques devant l’informatique est de plus en plus sensible et douloureux pour de nombreux collègues ». Effectivement j’entends souvent des jugements comme « à force de faire de l’informatique, on n’a plus le temps de faire de vraies maths ». Cet article, écrit volontairement à la première personne du singulier, présente un point de vue quelque peu contraire à celui qui prédomine : Non seulement il y a des « vraies maths » dans l’informatique, mais il y en a probablement plus que dans les maths.

Avant de chercher en quoi l’informatique peut menacer les « vraies maths », il conviendrait peut-être de s’interroger sur l’opinion que l’on se fait des « vraies maths », et en particulier, à quoi peuvent ressembler les « fausses maths » ainsi définies par contraste.

Les « vraies maths »

L’hypothèse la plus simple est que les « vraies maths » seraient les mathématiques pures. Elles comprendraient donc essentiellement (à l’heure actuelle)

  • La logique mathématique (très peu présente dans les programmes il faut l’avouer) ;
  • L’arithmétique (actuellement enseignée très peu au collège et en cycle terminal, uniquement en Terminale S spé maths, soit pour une minorité d’élèves) ;
  • L’algèbre, un peu en voie de disparition à en juger par le report à la classe de Seconde de la notion de produits remarquables ;
  • La géométrie, vaguement explorée de façon expérimentale et sans théorie (même si certaines notions sont réintroduites depuis cette critique
  • L’analyse, essentiellement axée sur la notion de fonction numérique (et pas trop par exemple sur celle de continuité, pourtant essentielle pour l’algorithme de dichotomie, basé sur le théorème des valeurs intermédiaires) ;
  • Enfin, les probabilités et statistiques, pas nécessairement reconnues comme « pures » bien qu’elles réclament un niveau théorique exceptionnellement élevé pour les comprendre, si ne n’est pour les enseigner.

J’essayerai de montrer ci-dessous par des exemples, que l’enseignement de l’informatique peut aider à redécouvrir pratiquement tous les chapitres de « vraies maths », par le biais des fondements des mathématiques (de toutes les mathématiques !) à l’exception peut-être des statistiques.

Besoin de clarifier le vocabulaire

Le problème essentiel à mes yeux, qui se pose dans l’enseignement des « vraies maths », est le manque de consistance des cours et notamment des définitions des notions abordées. Citons encore une fois Daniel Perrin : « Je trouve désagréable de parler de choses que l’on n’a pas définies ». Et bien, justement, il y a de moins en moins de définitions dans les cours de « vraies » mathématiques... Quelques exemples :

  • En Terminale STMG, la loi normale est au programme alors qu’elle est basée sur des calculs d’intégrales impropres portant sur la loi normale, « définie » à l’aide d’exponentielles. Or ni la notion d’exponentielle ni celle d’intégrale ne sont au programme de STMG...
  • En Seconde, on aborde les intervalles de confiance sans avoir au préalable vu ce qu’est un intervalle (en tout cas pas assez pour pouvoir en décrire un comme disque de dimension 1) ;
  • En probabilité, on étudie les notions d’intersection, de réunion, de complémentaire d’un ensemble, alors que la notion d’ensemble est totalement hors programme.
  • La probabilité notée P est une fonction (la preuve, on note P(E) la probabilité de l’évènement E, c’est donc bien l’image de E par une fonction P) mais aucun étudiant de BTS n’est capable de définir la notion de fonction.
  • Idem pour la notion de fonction (ou fonctionnelle) réciproque, essentielle pour aborder les notions de racine carrée (réciproque du carré), de logarithme (réciproque de l’exponentielle), d’intégration (réciproque de la dérivation).
  • On demande à des élèves de tous niveaux de résoudre des équations, sans qu’ils sachent ni le sens du verbe « résoudre » ni ce qu’est une équation.
  • Le meilleur : Les lycéens doivent savoir distinguer une implication de sa réciproque mais il ne faut surtout pas leur expliquer ce qu’est une implication ni ce qu’est une réciproque !

Or en informatique, ce besoin de savoir de quoi on parle exactement, est tout aussi important que dans les exemples ci-dessus ; il n’y a qu’à regarder la définition d’une variable chez éduscol :

Un modèle rigoureux de la variable informatique consiste à dire qu’une variable est une étiquette collée sur une boîte qui peut contenir différentes valeurs. Le contenu de chaque boîte varie au cours de l’exécution d’un programme (ce qui n’est pas le cas d’une variable mathématique). Quand l’ordinateur évalue une expression dans laquelle figure une variable, comme x+4, le résultat de l’évaluation est la somme du nombre contenu dans la boîte d’étiquette x et de 4.

Il est difficile (pour le moins) de comprendre cette phrase si on n’a pas une notion solide de ce qu’est une expression et son évaluation. Autrement dit, des connaissances suffisantes en calcul formel pour voir le lien entre l’évaluation d’une expression dans un contexte, et la substitution d’une variable par une valeur. Dans l’exemple ci-dessus, calculer l’image de 5 par la fonction x+4 est une compétence nécessaire pour évaluer l’expression x+4 dans un contexte où la boîte d’étiquette x contient le nombre 5.

En résumé, comprendre la notion d’affectation d’une variable crée un besoin de relever le niveau en calcul formel, au moins sur la notion de substitution d’une variable [1].

PDF - 6.1 Mo
L’article de Daniel Perrin en PDF

Géométrie plane

Voici un exemple de programme Python fréquent en 2nde :

  1. from math import *
  2.  
  3. def distance(xA,yA,xB,yB):
  4. return sqrt((xB-xA)**2+(yB-yA)**2)
  5.  
  6. print(distance(2,3,5,7))

Télécharger

Ce script me met mal à l’aise, parce qu’il définit une fonction de R4 dans R et cette fonction est difficile, conceptuellement, à relier à la notion intuitive de distance : Dans la vie courante, lorsqu’on parle de distance, il s’agit de distance entre deux objets, et non entre 4 nombres. Comment alors améliorer ce script ? En se posant (et répondant à) des questions :

  1. Qu’est-ce qu’un point du plan ? La définition la plus proche de la tradition mathématique est un couple (et non une liste) de nombres. En Python, on note (a,b) le point d’abscisse a et d’ordonnée b.
  2. Comment noter les coordonnées du point A ? Le plus concis est d’appeler xA l’abscisse de A, et yA son ordonnée. En Python xA et yA sont des variables numériques (de type float) et on les crée par une affectation simultanée (xA,yA)=A là encore proche de la notation mathématique usuelle.
  3. Comment calcule-t-on la distance AB, connaissant les coordonnées de A et de B ? Là c’est plus long, mais le module math de Python possède une fonction hypot qui, à partir de deux nombres considérés comme les côtés d’un triangle rectangle, donne la longueur de l’hypoténuse de ce triangle. Il suffit donc d’appliquer cette fonction à xB-xA et yB-yA pour avoir la distance entre A et B.

Cela donne le script suivant :

  1. from math import *
  2.  
  3. def distance(A,B):
  4. (xA,yA) = A
  5. (xB,yB) = B
  6. return hypot(xB-xA,yB-yA)
  7.  
  8. print(distance( (2,3) , (5,7) ))

Télécharger

L’objet de cet exemple n’est pas de donner des cours de programmation en Python mais de montrer que Python permet de faire des choses relativement proches du langage usuel (ci-dessus on a calculé la distance entre les points de coordonnées (2,3) et (5,7) donc, entre deux points et non 4 nombres) à condition de se poser les bonnes questions, et la réponse à ces questions nécessite des connaissances mathématiques solides et cohérentes, sans lesquelles enseigner à programmer proprement risque d’être difficile.

Milieu

Continuons avec cette histoire de point vu comme un couple de nombres : Le milieu est un point associé à un segment ou à deux points. C’est le second choix qui a été fait ici, puisqu’on a déjà trouvé comment représenter un point en Python, et pas un segment. Comment calculer les coordonnées de ce point ? Ce sont la moyenne des abcsisses et la moyenne des ordonnées. Alors on commence par définir une fonction qui, à 2 nombres, associe leur moyenne (arithmétique) :

  1. def moyenne(a,b):
  2. return (a+b)/2.0

Télécharger

Cette fonction est utilisable dans la fonction milieu, qui renvoie un couple de nombres :

  1. def milieu(A,B):
  2. xA,yA = A
  3. xB,yB = B
  4. return (moyenne(xA,xB),moyenne(yA,yB))
  5.  
  6. print(milieu( (2,3) , (5,7) ))

Télécharger

L’affichage rappelle que le milieu de deux points est un point.

Vecteur

En géométrie repérée du plan, un vecteur est aussi un couple de nombres. Mais un vecteur peut aussi être défini par deux points (respectivement, son origine et son extrémité). Pour calculer les coordonnées d’un vecteur, on propose une fonction :

  1. def vecteur(A,B):
  2. xA,yA = A
  3. xB,yB = B
  4. return (xB-xA,yB-yA)

Télécharger

Ce qui permet de redéfinir la distance AB comme norme du vecteur :

  1. from math import *
  2.  
  3. def distance(A,B):
  4. (u,v) = vecteur(A,B)
  5. return hypot(u,v)

Télécharger

Droite

La notion de vecteur directeur permet de programmer de façon plus fonctionnelle l’équation réduite de la droite (AB) :

  1. def coefficient_directeur(A,B):
  2. (u,v) = vecteur(A,B)
  3. return v/u
  4.  
  5. def ordonnee_origine(A,B):
  6. xA,yA = A
  7. return yA-xA*coefficient_directeur(A,B)

Télécharger

On affiche l’équation réduite de (MN) ainsi :

  1. m = str(coefficient_directeur(M,N))
  2. p = str(ordonnee_origine(M,N))
  3.  
  4. print("y = "+m+"x+"+p)

Télécharger


Fonctions

L’héritage de Papert

Le nom de Logo (langage) signifie, en grec, langage (ainsi que logique). Le but de Papert en créant ce langage était d’aider les enfants à développer leurs compétences linguistiques en dialoguant avec la machine. Dès lors, si un enfant désirait dessiner un hexagone en entrant hexagone() [2] il se retrouvait avec ce genre de message :

NameError: name 'hexagone' is not defined

ceci avait deux buts :

  1. Faire comprendre à l’enfant l’importance de la rigueur orthographique
  2. Initier à la notion de vocabulaire : Si un message contient un mot que son destinataire ne connaît pas, le message est incompréhensible [3]

Le rêve de Papert était que les enfants découvrent par eux-mêmes la nécessité avant de communiquer (ici, avec la machine), de se mettre d’accord sur le vocabulaire. Mais que faire si l’incompréhension par la machine ne vient pas seulement d’une faute d’orthographe mais du fait que le mot hexagone ne lui est tout simplement pas connu ? Facile, dit Papert, il n’y a qu’à définir ce mot. Ce qui, en Python (descendant de Logo) se fait ainsi :

  1. def hexagone():
  2. for _ in range(6):
  3. forward(80)
  4. left(60)

Télécharger

On l’aura compris, "def" est l’abréviation de « définir » (et au passage cette définition pythonienne doit être précédée de l’importation des fonctions du module turtle). Avec cette définition de fonction, hexagone() ne donne plus de message d’erreur mais déclenche le dessin d’un hexagone régulier par la tortue.

Et une fois qu’un nouveau mot (comme hexagone) a été ajouté au vocabulaire, on peut s’en servir pour définir d’autres nouveaux mots :

  1. def fleur():
  2. for _ in range(6):
  3. hexagone()
  4. forward(80)
  5. right(60)

Télécharger

Le motif dessiné par ce script

est la base d’un pavage hexagonal du plan, mais là il faut une double boucle et on est hors sujet.

Ceci dit, Python a comme on l’a vu hérité de cette possibilité de définir les nouveaux mots du vocabulaire, sauf que ce ne sont plus des procédures qu’on y définit, mais des fonctions. Le concept de fonction est donc central en Python, et pour ne pas s’embrouiller, il est nécessaire de clarifier ce concept.

Pour définir la fonction cube en Haskell, on écrit

let cube = \x -> x*x*x

ce qui traduit « soit cube la fonction qui à x associe x×x×x »

Pour définir la même fonction en Python, on écrit quelque chose d’analogue [4] :

cube = lambda x: x*x*x

ou plus « basiquement » (mais moins haskellien) :

  1. def cube(x):
  2. return x*x*x

Télécharger

Dans tous les cas c’est cube(5) qu’on entre pour connaître le cube de 5, comme dans le cours de maths.

Mais c’est quoi une fonction ?

C’est bien beau de manipuler les fonctions (savoir les définir, les utiliser voire de façon récursive) mais c’est quand même mieux, quand on utilise ce mot « fonction », de savoir de quoi on parle, non ? Alors, de quoi parle-t-on lorsqu’on parle de fonction ? Voici une proposition de définition :

Une fonction (mathématiques) est une relation entre une (ou plusieurs) variable appelée antécédent et une (ou plusieurs) variable appelée image et dépendant de l’antécédent de façon univoque. Pour l’instant, on ne va pas se concentrer sur la définition d’une variable (voir plus bas avec l’algèbre) mais sur celle d’une fonction : Celle-ci est donc un cas particulier (« univoque ») de relation, et pour savoir ce qu’est une relation, on va se reporter à Gottlob Frege : Une relation est un ensemble de couples. Cela suppose qu’on sache ce qu’est un ensemble et ce qu’est un couple. Les couples (de coordonnées en l’occurence) ont été vus en géométrie plane et les ensembles seront vus plus bas avec les probabilités. Alors la fonction cube, définie par exemple sur le corps fini à 5 éléments, se définit ainsi en Python :

cube = { x: x**3%5 for x in range(5)}

On remarque que le couple (x,y) est noté x : y en Python [5]. En fait le double-point est une notation pour la flèche ⟼. Et pour représenter la fonction on peut faire simplement

print(cube)

ce qui donne

{0: 0, 1: 1, 2: 3, 3: 2, 4: 4}

ou plus "Bourbaki-compatible" [6] :

  1. for x in cube:
  2. print(x,"\u27fc",cube[x])

Télécharger

qui produit cet affichage :

0 ⟼ 0
1 ⟼ 1
2 ⟼ 3
3 ⟼ 2
4 ⟼ 4

Cet affichage est la trame d’un diagramme sagittal (l’ensemble de départ dans une patate d’où partent les flèches, l’ensemble d’arrivée dans une autre patate où arrivent les flèches) :

Application versus fonction

Les spécialistes de Bourbaki objecteront, à raison, que le mot « fonction » est plutôt réservé au cas où l’ensemble de définition ne coïncide pas avec l’ensemble de départ. Dans le cas contraire (tout au moins dans le cas fini), on parle d’application (mathématiques). C’est le moment d’évoquer comment on peut représenter, avec les dictionnaires de Python, une fonction qui n’est pas une application. L’idée est plutôt simple : Si un élément de l’ensemble de départ n’a pas d’image par la fonction, on note qu’il en a une mais qu’elle est égale à None. Voici l’exemple de la fonction inverse sur le corps à 5 éléments :

Version Python, 0 a un inverse qui est du rien :

(le fait que l’inverse de 2 modulo 5 est 3 signifie que modulo 5, 2×3=6 a un reste égal à 1 qui est l’élément neutre de la multiplication même modulo 5)

Version maths, 0 n’a pas d’inverse :

Puisqu’on en est à Bourbaki, la fonction ln définie sur ]0 ;+∞[ peut être prolongée par continuité en 0, en lui donnant la valeur -∞ (sa limite) en 0. On peut même la prolonger sur [0 ;+∞] puisque sa limite en +∞ est +∞. Toujours selon Bourbaki, il est naturel de continuer (c’est le cas de le dire) à appeler ln la fonction prolongée par continuité. Cela donne cette définition de la fonction ln :

  1. from math import *
  2.  
  3. def ln(x):
  4. if x<float('inf'):
  5. if x==0:
  6. return -float('inf')
  7. else:
  8. return log(x)
  9. else:
  10. return float('inf')

Télécharger

Ce script permet de vérifier qu’elle est bien définie en 0 :

for x in range(8):
        print(ln(x))

En effet il donne

-inf
0.0
0.69314718056
1.09861228867
1.38629436112
1.60943791243
1.79175946923
1.94591014906

De même, 0 peut avoir un inverse conformément à la norme IEEE754, et cet inverse est infini.


Algèbre

Une difficulté se pose aussi bien avec le calcul formel qu’avec la programmation : Celle que les élèves ont, de plus en plus souvent, à concevoir la notion de variable.

Comment évaluer l’expression $3x+5y-x^2+13$ ? Il faut considérer $x$ et $y$ comme des contenants, que l’on peut dessiner sous forme de boîtes étiquetées par $x$ et par $y$ respectivement : $3\boxed{\phantom{2}}_{x}+5\boxed{\phantom{1}}_{y}-\boxed{\phantom{2}}_{x}^2+13$. Si par exemple $x=2$ et $y=1$, l’évaluation se fait en mettant 2 dans chaque boîte $\boxed{\phantom{2}}_x$ pour avoir $\boxed{2}_x$ et un 1 dans chaque boîte $\boxed{\phantom{1}}_y$ pour avoir $\boxed{1}_{y}$. On obtient

$3\boxed{2}_{x}+5\boxed{1}_{y}-\boxed{2}_{x}^2+13$

ce qui, dans le cas présent, donne le nombre $3\boxed{2}+5\boxed{1}-\boxed{2}^2+13=3×2+5×1-2^2+13=6+5-4+13=20$

La pratique des évaluations d’expressions peut donc mener à une meilleure intuition du calcul formel, du moins de la substitution de variables, qui est fondamentale en calcul formel.

L’héritage de Herbrand et Gödel

Voici une proposition de cours [7], inspirée par les définitions du célèbre article de Gödel ; on suppose les notions de nombre et de couple déjà connues :

  • Une variable est un couple dont le premier élément est un nom (une chaîne de caractères) et le second élément est un nombre appelé valeur de la variable.
  • Modifier le premier élément d’une variable, c’est la renommer. Modifier son second élément, c’est l’affecter.
  • Une expression est définie récursivement ainsi :
    • Un nombre est une expression,
    • Une variable est une expression,
    • L’image d’une expression par une fonction (définition plus bas) est une expression,
    • La somme de deux expressions est une expression ;
    • La différence entre deux expressions est une expression [8] ;
    • Le produit de deux expressions est une expression ;
    • Le quotient de deux expressions est une expression ;
    • L’élévation d’une expression à une puissance dont l’exposant est une expression, est une expression ;
    • La mise entre parenthèses d’une expression en fait encore une expression.
    • Rien n’est une expression si ce n’est obtenu par les constructions précédentes.
  • Une fonction (définie explicitement) est une relation entre une (ou plusieurs) variable et une expression où intervient le nom de cette variable.

On convient, dans l’écriture d’une expression, de remplacer chaque variable par son nom. Par exemple dans l’expression x+5, on reconnaît la somme de l’expression x et de l’expression 5. Et si 5 est clairement une expression (parce que c’est un nombre), x est aussi une expression parce que c’est une variable même si elle n’est désignée que par son nom : x+5 veut dire « la somme du contenu de x, et de 5 ». Et évaluer une expression, c’est remplacer chaque nom de variable figurant dans l’expression, par la valeur de la variable. La substitution est le stade suivant : On remplace les noms de variable par des expressions éventuellement non numériques.

Variables symboliques

Résumons : Une variable est quelque chose de relativement simple (un nom et une valeur) alors qu’une expression est plus complexe parce qu’elle mélange nombres et variables (référencées par leur nom) dans un enchevêtrement d’opérations et de parenthèses nécessitant, pour les évaluer, des connaissances sur les priorités opératoires et la simplification d’expressions (développement, factorisation) que les programmes actuels ne permettent pas de consolider au collège. Et du coup, la notion d’affectation est bien plus complexe pour des élèves que l’on a insuffisamment formés au calcul formel, parce qu’on a préféré les former à la programmation Scratch ! Pour sortir de ce cercle vicieux, il est peut-être intéressant de commencer la présentation des langages de programmation textuels (Python, mais aussi les Basic des calculatrices) sans programmer d’emblée, en manipulant (et affichant) des expressions dans la console [9]. Pour Python, une console intéressante à utiliser lorsqu’on est confronté à une insuffisance en calcul formel, est celle de SymPy. Celle-ci comprend des variables de type symbolique pré-affectées, comme x par exemple.

Par exemple, si on entre

2*3+4**2

on obtient

22

qui est le résultat de l’évaluation de 2×3+4².

Si on entre

1/(1+1/2)

on obtient

$\frac{2}{3}$

qui montre à la fois le fonctionnement des parenthèses, et le fait qu’on est en calcul exact tout au moins pour les fractions.

Si on entre

1/(1+1/x)

on obtient

$\frac{1}{1 + \frac{1}{x}}$

qui généralise l’évaluation précédente. Mais maintenant si on entre

simplify(1/(1+1/x))

on obtient

$\frac{x}{x + 1}$

La pratique de ces évaluations d’expressions dont certaines sont formelles [10] familiarise avec les priorités opératoires, et avec l’idée selon laquelle, à la calculatrice tout au moins, mener un calcul, c’est essentiellement évaluer une expression. Même si le calcul est un calcul de dérivée :

simplify(diff(1/(1+1/x)))

qui donne

$\frac{1}{\left(x + 1\right)^{2}}$

ou un calcul de primitive :

integrate(1/(1+1/x))

qui donne

$x - \log{\left (x + 1 \right )}$

Le calcul propositionnel est également accessible à ce genre de console. Par exemple

2 < 5 < 10

donne

True

(5 est bel et bien compris entre 2 et 10)

On a d’ailleurs la même réponse si on fait

5 in range(2,11)

Mais

3*0.1 == 0.3

affiche

False

Pourquoi ? Parce que 0,1 n’est pas un flottant et des erreurs d’approximation ont eu lieu lors de cette évaluation. Pour en savoir plus, voir la partie sur les flottants plus bas. Une solution serait de tester

3*1/10 == 3/10

qui, au contraire, compare deux fractions et trouve cette-fois ci une égalité :

True

Les évaluations sous SymPy

On peut passer beaucoup de temps à évaluer des expressions (dont, sous SymPy, certaines sont formelles) avant d’aborder la programmation. La première chose à aborder si on veut programmer, est la notion de variable. Dans une console celle-ci est simple à manipuler, puisque si on entre le nom d’une variable, son contenu est affiché. Et une affectation est elle-même une expression ! Par exemple, si on stocke le nombre 8 dans a puis on divise le contenu de a par 2, on fait

qui affiche seulement le résultat de l’évaluation de la seconde ligne (l’affectation s’évalue à du rien et afficher du rien, c’est ne rien afficher) : 8.

Quelle est la moitié de a ? On entre a / 2 et on a l’affichage 4 : La moitié de 8 est 4. Par contre si on veut connaître la moitié de x, on fait x / 2 qui donne $\frac{x}{2}$.

Pour effectivement diviser a par 2, il faut donc une affectation :

qui affiche 4. Mais désormais a vaut 4, comme on peut s’en rendre compte en affichant répététivement son contenu.

Des boucles simples peuvent être écrites en Python, directement dans la console. Alors pour connaître la somme des 8 premiers termes (et la mémoriser dans la variable s) de la suite géométrique de premier terme 8 et de raison 1/2, on peut évaluer successivement dans la console ces expressions qui ne s’affichent pas :

  1. s = 0
  2. a = 8
  3. for _ in range(8): s += a; a /= 2

Télécharger

Ensuite, pour connaître la somme, on peut afficher s en entrant s qui produit l’affichage $\frac{255}{16}$

Et avec un premier terme quelconque ? Si, au lieu de mettre 8 dans a au départ, on met x, la manip précédente donne l’affichage $\frac{255 x}{128}$

Et avec une raison pas forcément égale à 1/2 ? Notons t la raison (c’est une des 4 variables symboliques disponibles au démarrage de SymPy). On évalue alors successivement (sans affichage) :

  1. s = 0
  2. a = x
  3. for _ in range(8): s += a; a *= t

Télécharger

Ensuite, si on entre s on obtient $t^{7} x + t^{6} x + t^{5} x + t^{4} x + t^{3} x + t^{2} x + t x + x$

La généralisation est une des composantes de la pensée algorithmique. Le calcul formel permet de voir une simplification, en entrant simplify(s*(1-t)). L’affichage $x \left(- t^{8} + 1\right)$, ce qui peut amener à la formule du cours, par simplify(x*(1-t**8)/(1-t)-s) qui affiche 0, prouvant ainsi l’égalité entre s et $\frac{x \left(- t^{8} + 1\right)}{- t + 1}$

Noter que pour cette activité, la boucle n’a pas besoin d’être écrite explicitement puisque des compréhensions sont elles aussi des expressions :

  1. sum([8*(1/2)**k for k in range(8)])
  2. sum([x*t**k for k in range(8)])

Télécharger

donnent les mêmes affichages que les expressions ci-dessus.

D’autres applications pédagogiques de SymPy (notamment à la statistique !) peuvent être vues dans cet article de Patrick Raffinat.


Probabilités

Qu’est-ce que c’est qu’une probabilité ? Une fonction, qui à chaque événement associe un nombre entre 0 et 1, qui mesure les chances que l’événement a de se réaliser. Alors du coup qu’est-ce que c’est qu’un événement ? Un ensemble. Avec l’axiomatique de Kolmogorov, la théorie des probabilités nécessite celle des ensembles, reliquat des « mathématiques modernes ». Or Python permet de faire des calculs sur les ensembles. Si Omega est une variable globale désignant l’événement certain, on obtient le contraire d’un événement E en soustrayant E à Omega. Et comme le nombre d’éléments d’un ensemble E est obtenu par len(E), on peut définir et calculer la probabilité par ce script :

  1. Omega = set(range(1,9))
  2.  
  3. def proba(evt):
  4. return len(evt)/len(Omega)

Télécharger

Ci-dessus on modélise un dé octaédrique, en convertissant en ensemble la liste des entiers allant de 1 (compris) à 9 (non compris). La probabilité d’avoir, en lançant un tel dé, au moins 6, se calcule alors par

  1. aumoins6 = set([6,7,8])
  2. print(proba(aumoins6))

Télécharger

ce qui affiche 0,375 comme probabilité.

Compréhensions

Le programme de 1ère (appliqué à partir de la rentrée 2019) dit que « La génération des listes en compréhension et en extension est mise en lien avec la notion d’ensemble. »

L’axiome de compréhension dit qu’un ensemble décrit par compréhension existe. Les langages de programmation modernes comme Ruby, Python, Haskell etc. permettent de construire des ensembles (mais aussi des listes ou autres) par compréhension.

Ceci permet de résoudre des équations. Mais au fait que signifie « résoudre une équation » ? Cela signifie « donner l’ensemble de ses solutions ». Voici des exemples :

Pour résoudre sur N l’équation x²-5x+6=0, on peut faire ainsi :

  1. def f(x):
  2. return x**2-5*x+6
  3.  
  4. S = {x for x in range(10) if f(x)==0 }
  5.  
  6. print(S)

Télécharger

On définit S comme l’ensemble des x entiers entre 0 et 9 tels que f(x)=0, c’est-à-dire l’ensemble des solutions de l’équation f(x)=0. L’affichage est bien celui des solutions : {2,3}

Certes ici on a utilisé le fait que les solutions sont entières et inférieures à 10. Mais l’énoncé demandait de résoudre sur N cette équation. Et cette technique marche bien avec certaines équations diophantiennes pour lesquelles on sait que les solutions sont bornées.

De même, si on sait (par modélisation par exemple) que la solution du système

  • 3x+5y=11
  • 8x+13y=29

sont entières, on peut la trouver par balayage. Mais on peut aussi la définir : La solution d’un système est un couple (x,y) et on veut le couple dont les composantes x et y satisfont

S={(x,y) for x in range(10) for y in range(10) if 3*x+5*y==11 and 8*x+13*y==29}

L’affichage obtenu est conforme à la notation mathématique : {(2, 1)}

Le programme de Seconde (mis en place à la rentrée 2019) parle de « Fonction renvoyant un nombre aléatoire » et demande d’« Écrire des fonctions renvoyant le résultat numérique d’une expérience aléatoire » : Cela habitue les élèves à l’idée que, malgré son nom, une variable aléatoire n’est pas une variable, mais une fonction (dépendant du hasard). Cet exemple est emblématique de la méthode dite « Singapour » où l’abstraction est facilitée par la manipulation.


Arithmétique

Quelques exemples

Lors d’études menées vers la fin du XIXe siècle sur la suite de Fibonacci, Édouard Lucas a découvert une variante de cette suite, qui a fait l’objet du sujet d’informatique (et non de maths) du Capes 2018. Au passage il a découvert un algorithme dit « de Lucas-Lehmer » pour tester la primalité des nombres de Mersenne. Cet algorithme est encore utilisé de nos jours pour établir les records de nombres premiers, comme le plus grand connu.

La résolution d’équations dipohantiennes peut parfois se faire par balayage, si les solutions sont bornées (par exemple pour chercher les éventuels points à coordonnées entières sur une ellipse). Mais pour les équations de Pell-Fermat où on cherche les points à coordonnées entières sur une hyperbole, on doit trouver un algorithme permettant de parcourir l’infinité de solutions existantes. Les itérateurs de Python aident à appréhender ce problème difficile (la simple existence de solutions ne peut déjà être testée par un algorithme, selon le théorème de Matiyasevich). Mais ces points illustrent plutôt comment les maths bénéficient indirectement de l’informatique,celle-ci donnant un intérêt nouveau à de vieilles questions (Diophante d’Alexandrie, c’était il y a longtemps...). Avec la notion de pgcd il en est tout autrement :

Le programme de Seconde (mis en œuvre à la rentrée 2019) donne comme exemple d’algorithme :

« Pour des entiers a et b donnés, déterminer le plus grand multiple de a inférieur ou égal à b ».

Une fois qu’on a réussi à programmer et tester l’algorithme, il serait étonnant qu’aucun élève ne s’étonne de l’existence de ce plus grand multiple : C’est l’axiome d’Archimède qui est à l’origine de beaucoup de travaux mathématiques depuis qu’Archimède a fait cette constatation [11]. La propriété archimédienne des ensembles de nombres permet par exemple d’effectuer une division euclidienne (le plus grand multiple en question étant le quotient euclidien de a par b). Calculer dans un corps non archimédien comme Z/pZ ou C est d’ailleurs déroutant à cause de cela. Et l’analyse non standard est basée sur des corps non archimédiens.

De même, « Déterminer si un entier naturel a est multiple d’un entier naturel b » est facile pour qui connaît le reste euclidien, beaucoup moins pour qui ne le connaît pas...

Pour calculer un pgcd, les listes en compréhension permettent d’exprimer facilement un « algorithme naïf », basé sur le sens même de ces 4 lettres : Maximum de la liste des diviseurs communs. Avant de savoir comment on calcule le pgcd (le travail de l’algorithme) on se demande qu’est-ce que c’est (le travail des maths). Cela nécessite des prérequis comme l’intersection, les relations d’ordre (partiel : la divisibilité, et total : l’ordre naturel des entiers), le fait qu’une partie non vide de N a un plus petit élément...


Logique

La programmation des booléens familiarise les élèves avec des notions de logique propositionnelle, y compris l’implication [12].

L’utilisation des compréhensions (en l’ocurrence, de Prolog et non de Python) pour résoudre des problèmes de logique de rallye 3e-2nde, est visible dans la partie "backtracking" de cet article. Là encore, la résolution de ces problèmes passe par des questions ontologiques sur ce qu’est un graphe, une matrice etc et réclame des connaissances mathématiques sur ces objets. Dans le langage institutionnel, on peut dire que la compétence « modéliser », très sollicitée lorsqu’on programme, va souvent porter sur la modélisation d’objets mathématiques (du moins lorsqu’on programme) et cela va nécessiter (dans la phase « verbalisation » du tryptique de Singapour) de définir ces objets, dans le cours, de manière à la fois rigoureuse et universelle.

Qu’est-ce qu’un flottant ?

Voici une proposition de définitions à rajouter dans le cours de 2nde ; on suppose les notions de nombre entier, de décimal et de fraction déjà définies, et on note Z l’ensemble des entiers, D celui des décimaux et Q celui des fractions :

On appelle fraction dyadique le quotient d’un entier par une puissance de 2.

Comme une fraction a été définie comme quotient de deux entiers, et que 2k est un entier naturel si k ∈ N, une fraction dyadique est une fraction, d’où son nom. Quant à l’adjectif, il laisse entendre qu’il y a aussi des fractions qui ne sont pas dyadiques. Mieux, il y a même des décimaux qui ne sont pas dyadiques ! On en verra tantôt mais déjà, une première proposition :

Toute fraction dyadique est décimale.

Preuve : Soit x=a/2k une fraction dyadique ; en multipliant en haut et en bas cette fraction par 5k, on obtient x=a×5k/10k cqfd

Si on note D2 l’ensemble des fractions dyadiques, on a donc D2DQ donc les fractions dyadiques sont bien des fractions ! Qu’en est-il de la réciproque ?

La fraction 1/5=0,2 n’est pas dyadique.

Preuve : Par l’absurde, supposons qu’il existe a et k tels que 1/5=a/2k ; alors, par produit en croix, on aurait l’égalité a×5=2k. Or 2k n’a qu’un seul diviseur premier qui est 2, et ne saurait être divisible par 5 comme l’est a×5. La conclusion étant contradictoire, l’hypothèse l’est aussi (par modus tollens) et il n’existe aucune fraction dyadique égale à 0,2.

Des résultats similaires apparaissent pour des nombres comme 1/10=0,1 ou 3/10=0,3 qui sont décimaux sans être des fractions dyadiques. En résumé, on a la chaîne suivante d’implications strictes entre ensembles de nombres : NZD2DQR (à comparer avec la chaîne d’inclusions au programme de 2nde : NZDQR).

L’inclusion stricte entre les fractions dyadiques et les décimaux est illustrée par ce diagramme d’Euler : La plus petite patate, qui contient des fractions dyadiques, est entièrement à l’intérieur de la grosse patate qui contient des nombres décimaux :

On peut déjà imaginer rapidement deux applications pédagogiques de ces implications :

  • (histoire des maths) : La gamme de Pythagore est construite par application itérée des deux transformations suivantes :
    • monter d’une quinte (exacte, comme de do à sol), ce qui revient à multiplier la fréquence du son par 3/2=1,5 ;
    • descendre d’une octave (de do au do précédent) ce qui revient à diviser par 2.

Si on part d’une fréquence entière (typiquement, 256 Hz pour le jeu de tuyaux « 2 pieds » d’un orgue) ou toute autre fraction dyadique, on ne construit par ces procédés, que des fractions dyadiques. La gamme de Pythagore est donc formée de fréquences qui sont des fractions dyadiques (et même des entiers si on a choisi 256 Hz comme do de référence).

Le rapport de fréquences entre do et sa sixte la s’écrit (du moins lorsque c’est un la pythagoricien) 27/16=1,6875. Cette note (le la pythagoricien) est proche de la sixte naturelle correspondant à un rapport de fréquences égal à 5/3≈1,6667. Or cette fraction n’est pas dyadique (elle n’est même pas décimale). On a donc un exemple historique d’approximation d’un nombre par une fraction dyadique.

Remarque : Le la naturel 5/3 n’a pas obtenu l’approbation des pythagoriciens parce que ceux-ci se méfiaient du nombre 5 qui intervient dans l’écriture de cette fraction, et qui ne fait pas partie de la triade 2-3-4. Kirnberger a tranché entre les deux sixtes en leur substituant 23/4≈1,6818 qui est la sixte tempérée. Depuis la publication, par J.S. Bach, d’un recueil pour clavecin accordé selon le choix de Kirnberger, la gamme tempérée a supplanté à la fois la gamme naturelle et celle de Pythagore dans la musique occidentale.

  • (algorithmique et programmation) Les flottants de Python sont en fait des fractions dyadiques [13]. On en déduit, par un syllogisme de type Baroco, que le nombre 1/5=0,2 et sa moitié 1/10=0,1 ne sont pas des flottants ! La conséquence pratique de ce phénomène, bien connue, est que le nombre 1/10 ne peut être représenté, en tout cas comme flottant de Python, que sous forme approchée (par exemple, sur mon ordinateur, c’est la fraction dyadique 3602879701896397/255 qui approche 1/10 ; l’erreur d’approximation est inférieure à 3×10-17). Du coup, des erreurs d’approximation apparaissent lorsqu’on essaye ce script :
  1. print(3*0.1)
  2. print(3*0.1==0.3)

Télécharger

La remédiation est assez simple : Au lieu de travailler sur les flottants, lorsqu’on désire éviter ce genre de phénomène, on travaille sur des décimaux (type hors programme en 2nde !) avec par exemple ce genre de script :

  1. from decimal import *
  2. print(3*Decimal(1)/10)
  3. print(3*Decimal(1)/10==Decimal(3)/10)

Télécharger

Tout ceci semble, a priori, montrer plutôt comment les maths peuvent venir au secours de l’informatique, mais si une connaissance solide des ensembles de nombres et de leurs inclusions mutuelles s’avèrent nécessaire pour mieux comprendre de simples calculs en Python, ne peut-on considérer, une fois de plus, que les maths, pointant leur nez là où l’informatique ne les attendait pas, se voient revenir par besoin ? Dans ce cas l’informatique sauvera bien les maths par nécessité...


Conclusion

Le point de vue, très personnel, défendu ici, est que

  • si on veut enseigner correctement l’informatique théorique, on a besoin de bases mathématiques (en post-bac : fonctions dérivables de la variable complexe, intégration par la méthode des résidus, rayon de convergence d’une série entière ou d’une série de Laurent, algèbre linéaire, théorie des ensembles etc) bien plus solides que l’existant [14]. Un exemple plus de niveau lycée se trouve dans le programme de NSI en 1ère, où l’on doit prouver aux élèves que les algorithmes de tri présentés sont de complexité au pire quadratique : Ce genre de résultat vient de ce que, pour tout trinôme ax²+bx+c, il existe A tel que pour tout x suffisamment grand, ax²+bx+c<Ax². Comment expliquer ça à quelqu’un qui ne sait pas ce qu’est une inégalité, un trinôme ?
  • Et si on veut seulement enseigner correctement la programmation, finalement c’est un peu pareil, on s’appuiera rapidement sur des notions comme l’arithmétique, le calcul formel, les applications entre ensembles finis, la logique du premier ordre, la numération et d’autres notions mathématiques qui étaient présentes à l’époque des « maths modernes » (introduites pour mieux préparer les élèves au tsunami de l’informatique) et que l’on a donc jugé bon de supprimer des programmes.

Je suis persuadé qu’on ne peut pas enseigner correctement l’informatique à des élèves qui n’ont pas un bon, voire un très bon, niveau en maths, et ce besoin fera que oui, selon moi, l’informatique sauvera les maths, par nécessité.


ps

Le sujet n’est pas si nouveau que ça ; par exemple voici comment Guillaume Connan

Y a-t-il des maths plus « vraies » que ces maths-là ?

Sur cette problématique, voir aussi cet article à propos du rapport de l’Académie des Sciences

notes

[1Le logiciel SymPy est d’une grande aide pour cela

[2ici les exemples ont été traduits depuis Logo vers Python

[3C’est la principale raison des difficultés qu’endurent mes élèves en maths : J’utilise des mots dont ils ne connaissent pas la signification, comme isocèle, variable, fonction, probabilité, limite, médiane etc. N’est-il pas alors nécessaire de consolider avant tout le vocabulaire des élèves ?

[4cube est une variable, affectée à la fonction qui, à x, associe x×x×x. La version haskell s’écrit, en maths, cube := λ x ⟼ x3

[5Autrement dit, en Python, une fonction entre ensembles finis est codée par un « dictionnaire ».

[6L’image de x par un dictionnaire f est alors notée f[x] et non f(x).

[7fait en BTS dans l’exposition des prérequis

[8Définition redondante, puisque opposé est une fonction, donc l’opposé d’une expression est une expression, et la différence entre a et b est la somme de a et de -b.

[9ou la calculatrice, dont le système d’exploitation est du type repl, acronyme signifiant "Read, Evaluate and Print in a Loop" : Ce qui est lu, évalué et affiché en boucle, ce sont bel et bien des expressions.

[10par exemple sous forme de questions flash de calcul mental : on vidéoprojette la console de SymPy et on demande à des élèves de trouver mentalement le résultat qui sera affiché, avant d’appuyer sur « entrée »

[11que l’on peut formaliser dans le vacabulaire de la tortue Logo : Si une tortue répète assez souvent l’opération consistant à avancer d’une distance a, elle finira tôt ou tard par dépasser la longueur b ; c’est le nombre de répétitions qui est demandé par l’algorithme

[12grâce à l’évaluation paresseuse des booléens, les deux scripts Python suivants ont le même effet, si on les précède de

  1. from random import *
  2.  
  3. def(n):
  4. return randint(1,n)

Télécharger

Le premier script ressemble à une implication :

  1. if(6)==1:
  2. print("Bravo tu es tombé sur un as")

Télécharger

Le second est une disjonction :

(6)>1 or print("Bravo tu es tombé sur un as")

Cette équivalence entre les deux programmes se comprend si on connaît la définition de l’implication comme disjonction.

[13à part trois d’entre eux : +∞, -∞ et "NaN" qui est un flottant non numérique parce que non comparable en terme d’ordre de grandeur avec les autres flottants.

[14Voir par exemple cette présentation de l’algorithmique comme une science aux antipodes de ce qu’on enseigne sur le nom très galvaudé d’« algorithmique » en cycle 4 et au lycée.

Réagir à cet article
Vous souhaitez compléter cet article pour un numéro futur, réagir à son contenu, demander des précisions à l'auteur ou au comité de rédaction...
À lire aussi ici
MathémaTICE est un projet
en collaboration avec
Suivre la vie du site Flux RSS 2.0  |  Espace de rédaction  |  Nous contacter  |  Site réalisé avec: SPIP  |  N° ISSN 2109-9197