# Mathématiques avec Python et Ruby/Version imprimable2

* Si vous imprimez cette page, choisissez « Aperçu avant impression » dans votre navigateur, ou cliquez sur le lien Version imprimable dans la boîte à outils, vous verrez cette page sans ce message, ni éléments de navigation sur la gauche ou en haut.
* Cliquez sur Rafraîchir cette page pour obtenir la dernière version du wikilivre.
* Pour plus d'informations sur les version imprimables, y compris la manière d'obtenir une version PDF, vous pouvez lire l'article Versions imprimables.
Une version à jour et éditable de ce livre est disponible sur Wikilivres, une bibliothèque de livres pédagogiques, à l'URL : https://fr.wikibooks.org/wiki/Math%C3%A9matiques_avec_Python_et_Ruby

# Nombres en Ruby

Le langage Ruby est faiblement typé, ce qui veut dire que c'est au moment de la première affectation d'une variable (son instanciation) que Ruby devine le type de cette variable. Ruby possède 5 catégories de nombres:
* Les nombres entiers;
* Les fractions (quotients d'entiers par des entiers);
* Les réels (en réalité des nombres décimaux);
* Les grands nombres (Big_Num);
* Les nombres complexes.
** Nombres entiers
** Fractions
** Réels
** Complexes
** Quaternions

# Nombres entiers en Ruby

La particularité des nombres entiers, c'est que chacun possède un successeur et un prédécesseur. Et bien Ruby sait les calculer (certes ce n'est pas très difficile, il suffit d'additionner ou soustraire 1 à un nombre entier pour avoir le suivant ou le précédent).

## Obtention d'un nombre entier
### Avec une chaîne de caractères

Si on entre le script suivant:
on a exactement le même effet que si on entre
du moins en apparence. Parce que si on essaye d'additionner 2, avec
on a 9, alors qu'avec
on a un message d'erreur: On ne peut pas additionner un nombre et une chaîne de caractères !
Pour convertir une chaîne de caractères en entier, on utilise la méthode to_i de celle-ci. Ainsi
donne bien 9.
Un autre moyen d'obtenir un entier (naturel) avec une chaîne de caractères, c'est de compter le nombre de lettres de celle-ci. Ce qui se fait avec sa propriété length:

### Avec un réel

La méthode to_i permet aussi de convertir un réel en entier. Ce qui est parfois nécessaire parce que pour Ruby, ${\sqrt {100}}$ n'est pas un entier:
Affiche false parce que pour Ruby, le nombre calculé est 10.0 (considéré comme réel et non comme entier) et sa méthode to_i change son type, en le transformant en un entier:
affiche bien true.
n'a peut-être pas l'effet escompté, puisque a a été choisi proche de 4, et qu'on obtient 3. C'est que la conversion en entier se fait par une troncature et pas par un arrondi. En fait to_i a le même effet que floor:
Si on veut arrondir au-dessus, on utilise la méthode ceil d'un réel:
mais là on tombe dans le problème inverse:
donne aussi 4 !
Pour arrondir au mieux, on utilise la méthode round:

### Avec un entier

Pour avoir le successeur d'un entier, on utilise la méthode succ:
nous apprend que 7+1=8 (on s'en doutait un peu...), alors que
montre que 7-1=6. Mais contrairement au premier des axiomes de Peano, 0 possède un prédécesseur (-1) parce que pour Ruby, les entiers sont relatifs et pas seulement naturels.
Pour avoir l'opposé d'un entier, on le précède d'un signe "moins". Ainsi,
Donne 5, car l'opposé de -5 est 5.

### tests sur les entiers

Pour savoir si 2 est entier (on ne sait jamais), on peut le vérifier par
Ce test a été utilisé ci-dessus pour vérifier que 10 est entier, et on a eu raison de se méfier !
On peut aussi vérifier si un entier est premier, avec mathn:
nous apprend que 4 294 967 297 n'est pas premier, contrairement à ce qu'avait conjecturé Fermat.

## Opérations
### Addition, soustraction et multiplication

Dans Ruby, les opérations arithmétiques sont notées +, - et * sans grande surprise. Ces opérations peuvent porter sur des entiers négatifs:

### Division

Par défaut, la division des entiers est la division euclidienne. Son quotient est donc un entier (et n'est pas le quotient exact)

#### Quotient

le script suivant:
affiche 1 et pas 1,5 parce que le quotient euclidien de 3 par 2 est 1 (avec un reste de 1) et pas 1,5...
Si on veut le quotient exact, on doit remplacer l'un des entiers par un réel avec un point décimal. Pour avoir 1,5, on peut essayer l'une des possibilités suivantes
Mais dans ce cas, on travaille sur des valeurs approchés. Pour avoir les valeurs exactes, il faut utiliser des fractions (voir à Mathématiques avec Python et Ruby/Fractions en Ruby). Et bien entendu, toute tentative de division par 0 donne un message d'erreur.

#### Reste

Lorsqu'on divise euclidiennement 13 par 8, le quotient est donc égal à 1. Mais il reste 5. Pour calculer directement ce reste en Ruby, on peut utiliser le symbole %:
Cette opération permet de travailler sur les congruences. Remarque: Si b=0, on a le même message d'erreur que lorsqu'on divise par 0.

#### Primalité

En Ruby, l'opération pgcd est infixée. Pour chercher le plus grand entier qui divise à la fois 13572468 et 12345678, on entre
Bien entendu, a.gcd(b) et b.gcd(a) donnent le même résultat.
De même, le ppcm se calcule de façon analogue avec a.lcm(b).
Lorsqu'un entier n'a pas de diviseurs non triviaux, il est dit premier, et on a vu ci-dessus qu'avec mathn on peut tester si un nombre est premier. Avec prime aussi:
Et en bonus, la décomposition en facteurs premiers!

### Puissances

L'opérateur d'élévation à la puissance se note avec l'astérisque de la multiplication, mais dédoublée:
pour vérifier que $4^{2}=2^{4}$ (Exercice: Quelles sont les autres solutions de l'équation $a^{b}=b^{a}$?)
Remarques:
* Si l'exposant est négatif, le résultat est une fraction;
* Si l'exposant est réel, le résultat est réel aussi.

#### Priorités opératoires

En Ruby comme en algèbre, on effectue dans l'ordre
* Les parenthèses
* Les fonctions (comme l'élévation à une puissance)
* Les multiplications et divisions
* Les additions et soustractions.
Ainsi
affiche 17 et non 25: Les opérations ne sont pas effectuées de gauche à droite, mais en suivant les priorités opératoires.

## Entiers et itération
### Itérateur

La méthode la plus utile d'un nombre entier est sans conteste le bouclage, qui permet de répéter quelque chose de répétitif. Il suffit de dire à Ruby ce qu'il doit répéter (entre do et end) et combien de fois il doit le répéter: Un entier!

#### Bis repetita

Pour écrire un message très enthousiaste, on peut écrire

#### Avec un indice

Pour additionner les entiers successifs, on peut le faire avec
Le fait de mettre la variable entre traits verticaux lui donne automatiquement les valeurs entières successives. Mais la somme est affichée égale à 45 alors que 1+2+3+4+5+6+7+8+9+10=55...
Pour savoir d'où vient cette erreur de comptage, on peut essayer
Bingo! Les 10 premiers entiers naturels vont de 0 à 9, pas de 1 à 10.
Pour éviter de commencer par 0, on peut explicitement commencer par 1:
Mais cette fois-ci, on ne travaille plus avec un entier mais avec une liste d'entiers. Pour un tel objet, inject est une méthode typique de Ruby qui permet d'injecter à la liste un bloc d'instructions. Le bloc comprend deux variables locales, la première des deux (somme) étant destinée à se faire injecter des doses successives du médicament, la seconde (indice) représentant les doses de médicament à injecter l'une après l'autre.

### Boucles

Ruby permet aussi de faire de la programmation impérative avec des boucles:

#### à nombre prédéterminé d'exécutions

Pour additionner les entiers de 1 à 10, on peut aussi faire comme ceci:
Cette fois-ci on a bien 55.

#### à condition de sortie

La même somme peut aussi être calculée avec cette boucle:

# Fractions en Ruby

"Dieu fit le nombre entier, le reste est l’œuvre de l'Homme", disait Leopold Kronecker. Le début du reste ce fut incontestablement les fractions, définies comme quotients d'entiers, et pratiquées bien avant les nombres décimaux.

# Obtention d'une fraction

Pour entrer la fraction ${\frac {24}{10}}$, on peut entrer
qui la simplifie automatiquement. Alternativement, on peut charger mathn, ce après quoi le symbole de division donne des fractions au lieu de la division euclidienne:
On peut également obtenir une fraction à partir d'un réel, avec la méthode to_r (r comme rational). Mais la fraction n'est correcte que si son dénominateur est une puissance de 2:
Certes, ${\frac {5404319552844595}{4503599627370496}}\simeq {\frac {6}{5}}$ mais tout de même...

# Propriétés d'une fraction
## Numérateur

Pour avoir le numérateur d'une fraction f, on entre f.numerator:

## Dénominateur

Pour avoir le dénominateur d'une fraction f, on entre f.denominator:

## Valeur approchée

Pour avoir la valeur approchée d'une fraction, on convertit celle-ci en un réel:

# Opérations sur les fractions
## Opérations unaires
### Opposé

L'opposé d'un nombre, en particulier d'une fraction, s'obtient en le faisant précéder d'un signe -:

### Inverse

Pour obtenir l'inverse d'une fraction, on divise 1 par celle-ci:

## Addition

Pour additionner deux fractions, on met le signe + entre elles, et le résultat est une fraction (même si celle-ci est entière, comme par exemple ${\frac {1}{1}}$):

## Soustraction

La différence de deux fractions est une fraction :

## Multiplication

Le produit de deux fractions est une fraction :

## Division

Le quotient de deux fractions (à condition que la deuxième ne soit pas nulle) est une fraction :
Et même le reste euclidien est défini entre fractions, et le résultat est encore une fraction :

### Exemple

On voudrait savoir quel est le rapport des longueurs des tuyaux d'orgue :
* Entre un gros Nasard et un Nasard;
* Entre un gros Nasard et une grosse Tierce.
Ces rapports sont affichés par Ruby sous forme de fractions, même le premier d'entre eux qui est entier (ce qui ne sautait pas aux yeux !) :

## Puissance

Une puissance entière (même négative) d'une fraction) est encore une fraction :
Mais si l'exposant est décimal, même si le résultat est une fraction, Ruby le considère comme un réel :

# Algorithmes
## Réduite de Farey

Pour calculer la médiane (ou réduite) de Farey de deux fractions a et b, on définit une fonction Ruby de deux variables, qui s'appelle Farey :

## Fractions égyptiennes

Pour écrire une fraction à l'égyptienne (comme somme de fractions de numérateur 1), on applique l'algorithme de Fibonacci :
On peut résumer ce script Ruby aux étapes suivantes :
* On commence par extraire la partie entière de f, pour qu'il reste une fraction inférieure à 1 ;
* On soustrait à f (fraction restante) le plus grand inverse d'entier possible...
* On s'arrête quand le reste est lui-même un inverse d'entier (autrement dit, on continue tant que son numérateur est plus grand que 1).
* On ajoute à la liste, la dernière fraction obtenue.

# Écriture décimale

Depuis l'apparition de chiffres arabes et de la numération de position, les nombres décimaux sont devenus plus concrets que les fractions: En écrivant ${\frac {6}{5}}$, on voit deux nombres et on a tendance à oublier que cette écriture désigne un seul nombre (le quotient de 6 par 5). Alors qu'en écrivant ce nombre 1,2 on voit immédiatement qu'il n'y en a qu'un seul !

## Decimaux

Un nombre décimal est un nombre dont le développement décimal s'arrête quelque part. Les réels non décimaux sont donc ceux dont le développement décimal est infini, et on peut en construire exprès de cette manière comme le fit Liouville par exemple.
En Ruby, certains nombres décimaux ont quand même une infinité de chiffres parce qu'ils sont stockés en machine sous forme binaire et que, sous cette forme, ils ont une infinité de chiffres.

## Fractions

Le développement décimal d'une fraction se remarque par le fait qu'un motif finit par se répéter indéfiniment, comme le montrent les exemples suivants:

## Nombres irrationnels

Les premiers nombres irrationnels connus ont été les racines carrées des nombres entiers et le nombre d'or.
D'autres sont e et $\pi$:
Voici comment on peut calculer en Ruby la constante de Champernowne:
Le premier objet qui a été créé ci-dessus est une chaîne de caractères. Ruby le sait parce qu'on l'a mise entre guillemets. Initialement elle comprend le début de la représentation décimale de la constante (ou 0 suivi du point décimal). Le deuxième objet créé ci-dessus est une liste d'entiers (allant de 1 à 40). Cet objet est créé au vol, sans lui donner de nom, parce que la seule chose qu'on veuille faire avec lui, est d'appeler sa méthode collect qui fonctionne un peu comme le times des entiers: Un bloc d'instructions, entre accolades, avec un indice qui parcourt les éléments successifs du tableau, et ... une seule instruction, de concaténation de n (une fois transformé en chaîne de caractères avec to_s) et de la constante en cours de construction. Ceci fait, la constante est donc une chaîne de caratères, que Ruby peut transformer en un réel (flottant) ou en une fraction (rationnel).

# Fonctions
## Opérations

Les quatre opérations sont notées +, -, * et /. Dès que l'un des opérandes est écrit avec un point décimal, Ruby le reconnaît comme réel et l'opération donne un réel. La division peut même être euclidienne, ce qui permet notamment de calculer la valeur principale d'un angle en radians:
Le signe - peut aussi être unaire et dans ce cas, représente l'opposé du nombre qui le suit. Pour additionner un nombre h à un autre nombre x, on peut, au lieu de noter x=x+h, écrire x+=h.
Pour arrondir x à l'entier inférieur, on invoque x.floor; pour arrondir à l'entier supérieur, on invoque x.ceil. Pour calculer la valeur absolue de x, on invoque x.abs. Sa racine carrée se note indifféremment
En effet, l'astérisque dédoublé code l'élévation à un exposant en Ruby.

## Logarithmes et exponentielles
### Logarithmes

Le script ci-dessous calcule et affiche l'image de 0,5 par le logarithme népérien, par le logarithme décimal, par les fonctions réciproques du cosinus hyperbolique, du sinus hyperbolique, de la tangente hyperbolique:

### Exponentielles

Le script ci-dessous calcule et affiche l'image de 2 par l'exponentielle, par le cosinus hyperbolique, par le sinus hyperbolique, puis la tangente hyperbolique:

## Trigonométrie

Pour calculer les cosinus, sinus et tangente d'un radian, on peut faire comme ceci:
Pour connaître un angle en radians dont le cosinus, le sinus ou la tangente sont connus, on peut mettre un a devant la fonction:
Pour connaître un angle dont les côtés opposé et adjacent sont connus, on peut utiliser Math.atan(y/x) ou Math.atan2(x,y). Et même pour calculer ${\sqrt {x^{2}+y^{2}}}$, on peut utiliser Math.hypot(x,y). Par exemple, si on veut connaître les angles et l'hypoténuse d'un triangle rectangle de côtés 12 cm et 5 cm, on peut utiliser ce script:

# Nombres complexes en Ruby

On a inventé les nombres complexes juste parce qu'on voulait que certaines équations, comme $x^{2}=-1$, aient une solution (dans le cas présent, notée i). C'est typique des mathématiques, ça:
* On se fait un petit caprice;
* Pour le satisfaire, on invente une grosse théorie;
* D'autres gens utilisent cette théorie pour résoudre des problèmes, souvent issus des mathématiques appliquées, et qui n'ont plus rien de capricieux !

# Instanciation d'un complexe

Pour créer dans Ruby le complexe x+iy, on utilise Complex(x,y):
Les nombres x et y sont juste des nombres: Ils peuvent très bien être des entiers ou des fractions. On appelle entier de Gauss un nombre complexe dont les parties réelle et imaginaire sont des entiers relatifs.

# Opérations

La somme, la différence, le produit et le quotient de deux nombres complexes sont des nombres complexes:
Ces exemples illustrent le fait que la somme, la différence et le produit d'entiers de Gauss sont des entiers de Gauss. Par contre leur quotient exact ne l'est pas forcément. L'exemple de la soustraction montre que même lorsque le résultat d'une opération est réel, Ruby le considère quand même comme un complexe (de partie imaginaire nulle).
Ainsi,
On voit que pour Ruby, $i^{2}=-1+0i$ et non -1. On voit également que $i^{i}$ est réel. En effet, la puissance se note toujours ** en Ruby, et l'exposant n'est pas nécessairement réel.
Il est donc possible de calculer "la" racine carrée d'un complexe z avec z**0.5. Mais si 7+24i est le carré de deux complexes, "sa" racine carrée calculée par Ruby est 4+3i et non -4-3i. Comment Ruby choisit-il parmi ces deux nombres?
De même, -1 a deux racines carrées dans $\mathbb {C}$: i et -i. Ruby n'en reconnaît qu'une, et on se doutait qu'il choisirait i plutôt que son opposé. Mais
Si -1 est réel, il n'a pas de racine carrée du tout (sous-entendu dans $\mathbb {R}$), alors que si -1 est complexe, "sa" racine carrée est proche de i mais pas exactement égale à i (sa partie réelle étant de l'ordre de $10^{-16}$).

# Propriétés

Les parties réelle et imaginaire d'un complexe a sont des propriétés de celui-ci:
Il en est donc de même de son conjugué, qui est un complexe (contrairement à sa partie réelle, qui peut être un réel, mais aussi un entier ou une fraction, selon le cas).
D'autres propriétés d'un complexe sont son module et son argument:
z.polar permet d'avoir d'un coup le module et l'argument d'un complexe. Il permet de résoudre plus rapidement le problème vu dans le chapitre sur les nombres réels: Chercher le plus petit angle (en radians) et l'hypoténuse d'un triangle rectangle dont les côtés mesurent 12 cm et 5 cm:

# Fonctions

CMath contient des versions complexes des fonctions trigonométriques, exponentielles et logarithmes:

## Exponentielles

On peut retrouver l'écriture exponentielle des complexes de module 1 à condition de considérer l'exposant comme imaginaire (ci-dessous, pour vérifier numériquement que $e^{-{\frac {\pi }{3}}i}={\frac {1}{2}}+i{\frac {\sqrt {3}}{2}}$):
Comme d'habitude, 0,5 n'étant pas stocké très précisément en machine, l'égalité des parties réelles n'est qu'approximative.
Pour calculer les cosinus hyperbolique, sinus hyperbolique et tangente hyperbolique de 4+3i, on fait ainsi:

## Logarithmes

Pour calculer les images de 4+3i par les fonctions logarithme népérien, logarithme décimal, arguments des fonctions trigonométriques hyperboliques, on peut faire ainsi:

## Fonctions trigonométriques
### directes

Les cosinus, sinus et tangente d'un nombre complexe z se calculent avec le module cmath:

### indirectes

Les fonctions trigonométriques inverses se calculent de manière analogue, en mettant juste un C devant Math:
La fonction arc tangente se calcule aussi avec deux nombres complexes:
Ça doit sûrement servir à quelque chose, mais à quoi?

# Quaternions et octonions en Ruby
## Complexes

On a vu dans le chapitre précédent que pour Ruby, un nombre complexe z est essentiellement une structure abritant deux réels, accessibles par z.real et z.imag respectivement. La construction de Cayley-Dickson généralise ce point de vue: En prenant deux complexes a et b, on peut les regrouper dans une nouvelle structure qui est considérée comme un nombre: Un quaternion.
Dans toute la suite, on va profiter de la gestion des fractions offerte par cmath, avec

## Quaternions
### Definition et affichage
#### Définition

La définition d'un quaternion se fait dans une classe nommée Quaternion:
La première méthode, l'initialisation, crée donc deux variables a et b (qui seront des complexes, mais Ruby ne le sait pas encore):

##### Initialisation

Les nombres complexes a et b seront des propriétés du quaternion:

##### Propriétés a et b

Désormais on accède aux deux complexes a et b d'un quaternion q par q.a et q.b.

#### Affichage

Pour afficher un quaternion q avec puts(q), il est nécessaire de redéfinir (une sorte de surcharge) sa méthode de conversion en chaîne de caractères (string):
La notation des points se lit de droite à gauche, par exemple a.real veut dire la partie réelle de a et q.a.real, la partie réelle du a de q.
Le quaternion de Ruby ne possède alors que deux propriétés, a et b, mais on va se rattraper sur les méthodes, qui opèrent sur un quaternion (ou deux):

### Fonctions
#### Module

Le module d'un quaternion est un réel:

#### Conjugué

Le conjugué d'un quaternion est un quaternion de même module que celui-ci:

### Opérations
#### Addition

Pour additionner deux quaternions, on additionne leurs a respectifs, et leurs b respectifs, et on crée un nouveau quaternion à partir des deux nombres complexes obtenus:
Pour calculer et afficher la somme des quaternions p et q, il suffit alors d'entrer puts(p+q).

#### Soustraction

La soustraction des quaternions relève d'un principe analogue:

#### Multiplication

Le produit de deux quaternions est plus difficile à définir:
La multiplication des quaternions n'est pas commutative, comme le montre l'exemple suivant:

#### Division

Pour diviser un quaternion par un autre, on peut faire ainsi:
Comme ils ont le même module, le quotient d'un quaternion par son conjugué est égal à 1:
Cet exemple révèle que $\left(-{\frac {22}{30}}\right)^{2}+\left({\frac {4}{30}}\right)^{2}+\left({\frac {12}{30}}\right)^{2}+\left({\frac {16}{30}}\right)^{2}=1$, c'est-à-dire que $22^{2}+4^{2}+12^{2}+16^{2}=484+16+144+256=900=30^{2}$, qui est une décomposition de $30^{2}$ comme somme de 4 carrés.

### Résumé

La classe Quaternion de Ruby tient en entier dans un fichier plutôt léger, au vu de ses possibilités:
Si on enregistre ce fichier sous le nom quaternions.rb, il suffit d'insérer require 'quaternions' pour être en mesure d'effectuer des calculs sur les quaternions.

## Octonions

Ce qui est intéressant avec la construction de Cayley-Dickson utilisée ci-dessus pour les quaternions, c'est qu'elle se généralise: En définissant une structure (un objet) comprenant deux quaternions a et b, on définit un octonion.

### Définition et affichage
#### Définition

Comme pour les quaternions, on décrit l'objet octonion dans une classe Octonion:
Au passage on définit les propriétés a et b de l'octonion comme celles du quaternion, sauf que cette fois-ci ce ne sont plus des complexes mais des quaternions. Mais comme Ruby est faiblement typé, cette particularité n'apparaîtra que lorsque a ou b sera utilisé.

#### Affichage

Là encore, la méthode to_s se définit comme celle des quaternions, mais il y a 8 nombres à afficher au lieu de 4:
Pour accéder au premier de ces nombres, que est la partie réelle du a de a, on note a.a.real. Autrement dit, on parcourt un arbre binaire, de profondeur 3.

### Fonctions

Les fonctions sur les octonions se définissent presque comme celles sur les quaternions, Cayley-Dickson oblige:

#### Module

Comme pour les quaternions:

#### Conjugué
### Opérations
#### Addition

Comme pour les quaternions, on additionne les octonions composante par composante (a avec o.a, b avec o.b):

#### Multiplication

Non seulement la multiplication des octonions n'est pas commutative, elle n'est plus associative non plus:

#### Division

Là encore, le quotient d'un octonion par son conjugué est de module 1:

### Résumé

L'objet Octonion de Ruby est lui aussi, assez léger:
En l'enregistrant sous le nom octonions.rb, il suffit d'écrire
pour être en mesure d'effectuer des calculs sur les octonions en Ruby.

## Bibliographie

* En fait, les quaternions existent déjà sous Ruby, à condition de les télécharger: ; sur le même site, l'auteur propose aussi des octonions.
* Sur les octonions, le livre de John Baez est une lecture hautement conseillée:

# Ruby et probabilités

Comme tout langage de programmation qui se respecte, Ruby permet de calculer des nombres pseudoaléatoires, et donc de faire de la simulation de phénomènes aléatoires.
Mais parmi les objets que gère Ruby, il y a aussi les ensembles, donc les évènements.
** Évènements
** Nombres pseudo-aléatoires

# Ensembles en Ruby

Les évènements sont décrits en probabilité par des ensembles. Si ces ensembles sont finis, Ruby les gère.

# Construction d'évènements
## Évènements certain et impossible

L'évènement impossible, noté $\emptyset$, est entré en Ruby avec des crochets vides:
L'ensemble de toutes les issues possibles de l'expérience aléatoire, appelé univers, est noté $\Omega$.
Pour savoir si un élément se trouve dans un ensemble, on utilise include? comme dans omega.include?(6) pour savoir si l'évènement peut donner un 6.

## Avec un dé

On s'apprête à lancer un dé. Alors l'évènement "le résultat sera plus petit que 5" est décrit par l'ensemble $\left\{1,2,3,4\right\}$. De même, l'évènement "le résultat sera pair" est représenté par $\left\{2,4,6\right\}$. On construit aisément ces évènements avec la notation ensembliste de Ruby qui se fait avec des crochets au lieu des accolades. Mais la définition d'ensembles par description est possible avec Ruby:
Pour construire l'univers, on peut prend la liste des nombres allant de 1 à 6, et on la transforme en tableau avec to_a. Pour avoir les petits résultats (moins que 5), on choisit dans l'univers les éléments qui sont inférieurs à 5. select est une méthode de l'objet univers, qui se crée une variable r (entre traits verticaux) et lui fait parcourir les éléments du tableau (car univers en est un) et lui fait passer ou non par un filtre. En bref, on sélectionne les éléments de l'univers qui sont inférieurs à 5. De même, pour avoir les résultats pairs, on sélectionne les éléments de l'univers dont le quotient par 2 tombe juste (reste nul).

## Avec des cartes

Cette fois-ci, on extrait au hasard une carte parmi un jeu de 32 cartes.
On construit l'univers par un produit cartésien (des cartes avec Descartes !) entre l'ensemble des valeurs et celui des couleurs:
La troisième ligne transforme toutes les cartes en chaînes de caractères; en effet certaines d'entre elles étaient des chiffres. La suite du script consiste à créer un univers initialement vide, puis, avec la méthode collect du tableau des valeurs de cartes, à placer dans le jeu de cartes, l'une après l'autre, toutes les cartes (il est nécessaire de mettre une boucle à l'intérieur de la première, pour les différentes couleurs associées à chaque valeur de carte).
L'évènement "la carte est une figure" (pas un nombre) se construit en choisissant les cartes dont le début du nom n'est pas un nombre entier (donc se transforme en 0 lorsqu'on le convertit en entier):
Et pour construire l'évènement "la carte est un pique", on extrait les cartes de pique du jeu entier:
(on extrait les cartes dont le nom termine par ue, puisque seul le mot pique se termine ainsi).

## Évènements simultanés
### Notation

L'évènement "A et B" se note $A\cap B$, et l'opération se note en Ruby par une esperluette (&).

### Avec les cartes

Le script suivant montre que dans un jeu de 32 cartes, il y en a 3 qui sont à la fois des figures et des piques: Les trois figures de pique:

## Le "ou" inclusif
### Notation

De même l'évènement "A ou B" se note $A\cup B$, et en Ruby, le symbole pipe (trait vertical). Ruby enlève automatiquement les doublons.

### Avec les cartes

On peut compter les cartes qui sont des figures ou des piques:
...mais on peut aussi laisser Ruby les compter, il en trouve 17. Ce comptage est à la base des calculs de probabilité.

## Contraire

Pour calculer le contraire d'un évènement, on le soustrait à l'univers.

### Avec le dé

Ce qui montre que le contraire de "pair" est "impair".

### Avec les cartes
# Probabilités

La probabilité d'un évènement est définie comme le quotient de sa taille (en Ruby, size) par celle de l'univers.
On peut associer une probabilité à un évènement seul, en baptisant l'univers $univers ce qui fait qu'il est une variable globale, et en définissant une probabilité par
Mais pour éviter l'usage d'une variable globale, on peut aussi associer une probabilité à l'évènement et à son univers:

## Probabilités conditionnelles

Ci-dessus, on a défini les probabilités avec comme paramètre l'univers. En effet, cette variable est globale, donc inaccessible a priori dans le corps de la fonction. Ceci permet de remplacer l'univers par un autre évènement, et donc de définir la probabilité conditionnelle. Par exemple, avec le dé:

## Définitions

On peut alors définir des booléens concernant des évènements, en utilisant les propriétés de leurs probabilités:

# Nombres pseudo-aléatoires

Le traditionnel nombre pseudo-aléatoire compris entre 0 et 1 s'obtient avec
Si on veut un nombre entier aléatoire, on peut mettre le nombre d’occurrences possibles entre parenthèses après le rand. Par exemple, pour lancer un dé à 6 faces, on obtient avec rand(6) un nombre entre 0 et 5. Donc pour lancer un dé, on fait
Pour simuler une variable aléatoire binomiale de paramètres n et p, on peut utiliser le fait que celle-ci est la somme de n variables de Bernoulli indépendantes entre elles. Façon Ruby, cela peut se faire avec l'algorithme suivant (basé sur une analogie avec un jeu de pile ou face, où p est la probabilité d'avoir pile et n le nombre de lancers de la pièce):
* On crée un ensemble de n objets, par exemple une liste de nombres (1..n);
* On extrait de celle-ci les nombres victorieux (ceux pour lesquels une pièce est tombée sur pile);
* On compte les objets retenus.
En Ruby cela donne

# Lancer de dés
## Un dé

Pour voir si le dé est équilibré, on peut le lancer quelques milliers de fois et compter combien de fois chaque face est sortie... ou laisser faire le travail par Ruby:

## Deux dés

Pour lancer deux dés et additionner leurs résultats, on fait comme ci-dessus et on additionne. Seulement le tableau des effectifs est indexé de 0 à 10 (2 de moins que les résultats des lancers):

# Avec des cartes
## Tirer une carte au hasard

Puisque le jeu de cartes est un tableau, il suffit de choisir un indice au hasard pour tirer une carte au hasard. Par prudence, on va faire semblant de ne pas savoir qu'il y a 32 cartes dans le jeu (et qu'elles sont numérotées de 0 à 31). On va tirer 3200 fois une carte d'un jeu de 32 et compter le nombre de fois qu'on a eu un as de pique. Pour cela on va utiliser un compteur du nombre de victoires (gains) et on va lui injecter une unité chaque fois que le nom de la carte est 1 pique:

## Tirer 5 cartes au hasard

Pour constituer une main de 5 cartes, il suffit a priori de faire 5 fois l'opération précédente:
Seulement il peut arriver qu'on ait deux fois l'as de pique dans la même main ! En effet le script précédent réalise un tirage avec remise, pour lequel les calculs de probabilités sont plus faciles, mais irréaliste pour les jeux de cartes et le Loto. Ce dont on a besoin dans le cas présent, c'est d'un tirage sans remise, qui se produira en enlevant les cartes au fur et à mesure qu'on les met dans la main de 5 cartes.
Le jeu dont on a extrait les cartes est une variable locale, et à la fin de ce script il y a toujours 32 cartes dans l'univers.
Ensuite on peut compter les carrés d'as parmi 10 000 parties:
On construit une liste avec les cartes de hand dont le nom commence par un 1 suivi d'un espace (les as), et lorsque la longueur de cette liste est égale à 4, on incrémente le compteur carres. À la fin de l'exécution du script, on a donc le nombre de carrés d'as parmi les 10 000 tirages, et en le divisant par 10 000, on a la fréquence de ces carrés d'as. Elle est très faible !

## Mélanger un jeu de cartes

En 1741, dans les Mémoires de l'Académie des Sciences de Berlin, Leonhard Euler publiait un article titré Calcul de la probabilité du jeu de rencontre. Le nom initial du jeu de rencontre était jeu de treize parce qu'il se jouait à 13 cartes. Mais Euler généralise le jeu à n cartes.
Le jeu de rencontre est un jeu de hasard, où deux personnes ayant chacune un entier jeu de cartes, en tirent à la fois une carte après l'autre, jusqu'à ce qu'il arrive, qu'elles rencontrent la même carte: et alors l'une des deux personnes gagne. Or, lorsqu'une telle rencontre n'arrive point du tout, alors c'est l'autre des deux personnes qui gagne. Cela posé, on demande la probabilité, que l'une et l'autre de ces deux personnes aura de gagner.
Dans cet excellent article (16 pages en Français),
Pourvu donc que le nombre de cartes ne soit pas moindre que 12, l'espérance de A sera toujours à celle de B à peu près comme 12 à 7 ... Ou bien parmi 19 jeux qu'on joue, il y en aura probablement 12 qui font gagner A, et 7 qui feront gagner B.
Pour mélanger un jeu de cartes, on peut construire une main de 32 cartes ! Ensuite on peut répéter l'expérience 1900 fois, et compter combien de fois il y a eu au moins une rencontre (le nombre de rencontres strictement positif), et enfin, par division par 1900, estimer la fréquence de ces rencontres, et la comparer avec le quotient de 12 par 19 donné par Euler:
Un exemple de résultat sur 1900 jeux:
La valeur exacte de la probabilité d'une rencontre est donnée par Euler, dont la formule se traduit en Ruby par
et qui donne la valeur ${\frac {3122594362778744887436077703535391}{11610685876768858763797949063535391}}$...

# Méthode de Monte-Carlo

Pour calculer la valeur approchée de $\pi$ par la méthode de Monte-Carlo, on crée un nuage de points à coordonnées pseudo-aléatoires, et on compte combien d'entre eux sont à moins d'une unité de distance de l'origine du repère:
Le résultat est correct à trois décimales près.

# Ruby et analyse

** Suites
** Fonctions
** Analyse numérique

# Suites en Ruby

Une suite de nombres (éventuellement complexes) ne peut se représenter en machine parce qu'elle comprend une infinité de termes. Alors on n'en représente qu'une partie sous forme de liste de nombres. Et Ruby manipule très bien ce genre d'objets.

# Définition de suites
## Par fonction

Une suite est une fonction de $\mathbb {N}$ dans $\mathbb {R}$ (ou $\mathbb {C}$...). On peut donc facilement calculer les premiers termes de celle-ci en utilisant la méthode collect d'une liste d'entiers (approximation finie de $\mathbb {N}$). Par exemple pour vérifier que la suite $u_{n}={\frac {1}{n}}$ tend vers 0, on peut essayer

## Suites récurrentes

Pour une suite récurrente, chaque terme est défini à partir du précédent.

### Suite logistique

La suite logistique $u_{n+1}=4u_{n}\left(1-u_{n}\right)$ est chaotique sur [0;1]. Pour le vérifier, on peut faire
En constatant que $u_{0}=0,1={\frac {1}{10}}\in \mathbb {Q}$, on peut vérifier que, quoique chaotique, cette suite est formée de fractions:
Quoique chaotique, cette suite ne fait pas un bon générateur pseudo-aléatoire, parce que les nombres proches de 0 et 1 sont trop souvent visités. Pour le vérifier graphiquement, on peut dessiner un histogramme des 4000 premières valeurs de la suite, avec l'algorithme suivant:
* On fait comme ci-dessus, mais au lieu d'afficher u, on incrémente l'entrée d'un tableau des effectifs indexée par sa troncature. C'est ce tableau qui va être représenté graphiquement.
* Ensuite, on représente chaque effectif par un rectangle de largeur 4 pixels et de hauteur l'effectif correspondant. Les rectangles sont bleus, remplis de vert.
Le tout est fait en écrivant les instructions dans le langage svg, engendrées par Ruby, dans un fichier HistogramRuby1.svg visible ci-dessous. Voici le script au complet:
Et voici le fichier produit par le script:

### Suites arithmétiques et géométriques

Les suites arithmétiques et géométriques sont aussi des suites récurrentes.

#### Suites arithmétiques

Une suite est arithmétique de raison r si $\forall n,u_{n+1}=u_{n}+r$. Cette définition est récurrente.
Par exemple, si on place 2000 € avec des intérêts (simples) correspondant à 3 % du capital de départ, soit 60 €, on peut calculer les valeurs successives du capital pendant 20 ans avec

#### Suites géométriques

Une suite est géométrique de raison r si $\forall n,u_{n+1}=u_{n}\times r$. Les suites géométriques sont donc aussi récurrentes.
Si on place 2000 € à intérêts composés au taux de 2 % par an, l'affichage des valeurs successives du capital (arrondies à l'eurocent près) peut se faire avec
Sachant que chaque humain a deux parents et que chacun d'entre eux a aussi deux parents, etc. on peut dire que le nombre d'ancêtres à la génération n est géométrique de raison 2. Le nombre total d'ancêtres jusqu'à la génération n s'obtient par
On a presque autant d'ancêtres à la génération 21 qu'à toutes les générations précédentes cumulées!
Ce qui donne envie de vérifier si c'est pareil pour toutes les générations ou si c'est une spécificité de la génération 21:
On crée une liste des ancêtres jusqu'à la génération n comprise (genealogie) et une liste (generations) des nombres d'ancêtres à la génération n seulement. La lise test est constituée des entiers n pour lesquels le nombre d'ancêtres à la génération n n'est pas égal au total d'ancêtres jusqu'à la génération n-1 augmenté de 2 (avec reject, on a enlevé les positifs). La longueur de ce test est très petite !
Sous Ruby on peut aussi calculer des suites géométriques de raison complexe. La somme des termes est alors particulièrement intéressante à étudier (par exemple si la raison vaut i).

# Suites d'entiers
## Suite de Fibonacci
### Calcul des termes

La récurrence de la suite de Fibonacci est double, avec $u_{n+1}=u_{n}+u_{n-1}$. Son calcul pose donc un problème algorithmique, puisqu'il faut trois variables (les deux termes à calculer et une variable tampon pour stocker temporairement l'un des deux termes, afin qu'il ne soit pas écrasé par la somme). Ce problème n'existe pas en Ruby qui permet les affectations simultanées:
On peut aussi le faire de manière plus Ruby:

### Nombre d'Or

Pour étudier le quotient de deux termes successifs de la suite:
Mais en fait, les nombres de Fibonacci étant entiers, leurs quotients sont des fractions, et cette variante le montre:
On a donc une suite d'approximations rationnelles du nombre d'Or.

## Suite de Collatz

Algorithmiquement, la suite de Collatz est intéressante parce que son calcul est basé sur un test de parité, et qu'elle utilise une boucle à condition de sortie:

## Multiples communs

La suite des multiples de 5 et la suite des multiples de 7 sont arithmétiques de raisons respectives 5 et 7. On peut les construire en choisissant les nombres entiers qui sont divisibles respectivement par 5 et par 7:
Les multiples communs à 5 et 7 sont les multiples de 35, qui est le ppcm de 5 et 7. Cette construction est à l'origine de la théorie des idéaux par Kummer.

# Suites et séries

Une série est une suite dont le terme général est défini par une somme.

## Premier exemple

La suite définie par $u_{n}={\frac {1}{2}}+{\frac {1}{6}}+{\frac {1}{12}}+{\frac {1}{20}}+...={\frac {1}{1\times 2}}+{\frac {1}{2\times 3}}+{\frac {1}{3\times 4}}+{\frac {1}{4\times 5}}+...+{\frac {1}{n(n+1)}}=\sum _{k=1}^{n}{\frac {1}{k(k+1)}}$ tend vers 1, il est relativement aisé de le démontrer, et encore plus facile de le vérifier avec Ruby:
Cette suite est une suite de rationnels:
Cette variante suggère d'ailleurs une démonstration de la convergence, grâce à l'émission d'une conjecture sur le terme général de la suite...

## Deuxième exemple

La suite $u_{n}={\frac {n}{n^{2}+1}}+{\frac {n}{n^{2}+2}}+{\frac {n}{n^{2}+3}}+{\frac {n}{n^{2}+4}}+...+{\frac {n}{n^{2}+n}}=\sum _{k=1}^{n}{\frac {n}{n^{2}+k}}$ converge aussi, bien que ce ne soit pas évident en voyant son expression algébrique.
Là encore, la suite est rationnelle:

## Constante d'Euler

On peut la calculer (et vérifier la lenteur de la convergence) avec

# Applications
## Méthode de Heron

Pour calculer ${\sqrt {5}}$ avec la méthode de Heron, on utilise la suite itérée $u_{n+1}={\frac {u_{n}+{\frac {5}{u_{n}}}}{2}}$:
Mais encore une fois, cette suite qui converge vers ${\sqrt {5}}$ est formée de fractions. On a donc une suite d'approximations rationnelles de ${\sqrt {5}}$:
On en déduit des approximations rationnelles du nombre d'Or ${\frac {{\sqrt {5}}+1}{2}}$:
En comparant avec les quotients de nombres de Fibonacci successifs, on voit que la méthode de Heron converge beaucoup plus vite. Cette convergence peut se montrer en représentant graphiquement la suite, ce qu'on peut faire en plaçant des points dans un fichier svg:
Le fichier produit par ce script s'appelle SuiteRuby01.svg. Le voici:

## Formule de l'arc tangente

Comme on le voit, la suite converge très lentement.
Encore une fois, les termes de la suite sont rationnels, ce qui donne une suite de fractions approchant $\pi$:

# Fonctions en Ruby

En Ruby, une fonction s'appelle une méthode, mais du point de vue mathématique, ce n'est guère qu'une question de vocabulaire.

# Exemple
## Sujet Bac STG CGRH Métropole-Réunion Septembre 2007

$C(x)=x^{2}+50x+100$ pour $5\leqslant x\leqslant 40$
Et plus bas, dans le même exercice,
$f(x)={\frac {C(x)}{x}}$ pour x appartenant à [5 ; 40].

## Définition des méthodes

Donc pour Ruby, C et f seront des méthodes, dont l'antécédent s'appellera x et dont l'image sera envoyée par return:
Bien entendu, on pouvait aussi définir f directement par

# Tableau de valeurs
## Suite de l'énoncé du Bac STG 2007

Par la suite, on demande de reproduire et compléter le tableau suivant, arrondi au centième d'euro:
| x | 5 | 10 | 20 | 30 | 40 |
| f(x) | | | | | |

## Tableau de valeurs

Certes, avec une boucle, on peut calculer plein de valeurs de f(x) différentes:
mais on a trop de valeurs de x pour remplir le tableau. Une meilleure variante sera donc
qui est déjà bien plus léger à exploiter.
Plus typiquement Ruby:

## Image d'un ensemble par une fonction

Pour que la fonction f ne s'applique plus seulement à un réel, mais à tous les nombres du tableau, on utilise map (une méthode de l'objet tableau):
Cette notion d'image d'un ensemble par une fonction est à la base de pratiquement toute la géométrie: Alors que la symétrie centrale est définie comme une transformation qui associe un point à un point, on l'applique très vite à des ensembles de points comme dans l'expression la symétrique d'une droite par rapport à un point.

## Arrondis

Enfin, pour avoir les arrondis au centime près:
qui remplit le tableau presque immédiatement.

# Représentation graphique

Ruby n'étant pas très doué (pour le moment) en dessin, on va utiliser ses talents littéraires pour fabriquer un fichier au format svg. Ce fichier sera fabriqué comme une chaîne de caractères, et inscrit dans un fichier nommé FonctionRuby01.svg posté ci-dessous. Le fichier sera créé en mode écriture (w) avec

## Création de la figure

On commence par écrire dans le fichier (qui, on l'a vu ci-dessus, s'appelle figure), ce qu'il faut pour dire que c'est un fichier svg (l'entête):
Le fichier fera donc 640 pixels de large et 480 pixels de haut.

## Axes

Les axes et leurs graduations seront des traits, créés par des boucles puisque le travail des graduations est répétitif et que les boucles sont faites pour tout ce qui est répétitif.

### Des abscisses

L'axe des abscisses et ses graduations sera bleu:

### Des ordonnées

L'axe des ordonnées est en vert:

## Courbe

On va représenter graphiquement la fonction en rouge, sous forme d'un polygone à 350 côtés:

## Résultat

Pour que la figure soit reconnue, il reste encore à fermer la balise svg, ouvert au tout début de la figure, puis à fermer le fichier pour que Ruby le libère:
L'exécution du script ci-dessus produit le fichier suivant:
Certes, le fichier Ruby a l'air encore plus compliqué que le fichier svg mais il est possible de créer des méthodes axes et trait pour en simplifier la lecture.

# Analyse numérique en Ruby
## Fonction

Les algorithmes ci-dessous seront appliqués à la fonction f : $x\mapsto x^{2}-5$. On va donc commencer par créer une méthode pour cela:

## Résolution numérique d'une équation

Pour chercher à $10^{-14}$ près un antécédent de 0 par f, on peut utiliser la méthode de dichotomie:
Le script affiche une solution parce que f(1) est négatif et f(3) positif. Sinon on aurait un message d'erreur.

## Calcul approché d'un nombre dérivé

On approche la tangente par une sécante. On utilise une méthode centrée:
On voit que $f'(2)\simeq 4$

## Calcul approché d'une intégrale

La méthode des rectangles consiste à approcher $\int _{a}^{b}f(t)\,dt$ par la somme des aires des rectangles de largeur h et de hauteur f(a+nh) pour a+nh allant de a à b. On choisit N assez grand (ici 1 000 000) pour que h soit petit et l'approximation bonne:

# Ruby et géométrie

* Points
* Vecteurs
* Droites

# Points en Ruby

L'objet Point est une bonne manière d'aborder la programmation objet. En géométrie repérée, un point est constitué de deux nombres, son abscisse et son ordonnée.
$A(-1;3)$
$B(5;1)$
$C(1;5)$

# Classe

Pour que Ruby possède un objet Point, il suffit de le définir, sous la forme d'une classe:
Dorénavant, chaque fois qu'on crée un point par Point.new(x,y), celui-ci possédera les coordonnées x et y qui sont pour l'instant ses seules propriétés (des variables stockées temporairement dans l'objet).

# Coordonnées

Cependant pour accéder depuis l'extérieur aux coordonnées du point, il faut les redéfinir comme des méthodes Ruby (parce que dans Ruby, tout est méthode).

## Abscisse

Il suffit de dire que la méthode x renvoit le nombre x:
(à l'intérieur de la classe)

## Ordonnée

Idem pour y:
Dorénavant, l'abscisse de P s'appelle P.x et son ordonnée, P.y.

# Affichage

Pour afficher un objet, il faut utiliser la conversion to_s que Ruby propose. Dans le cas présent, puisqu'on a inventé un nouvel objet, on doit redéfinir cette conversion en chaîne de caractères en mettant les coordonnées entre parenthèses, séparées par un point-virgule:
Pour afficher un point M, on peut faire
mais aussi
puisque Ruby se charge automatiquement de la conversion to_s.

# Deux points

Le plus simple avec deux points, c'est le milieu, parce que c'est un objet de même type (un point):

## Milieu

La syntaxe est typique de Ruby: On parle de "milieu avec q" en invoquant

## Vecteur

Un peu hors sujet ici (on en reparlera dans le chapitre qui leur est consacré), le vecteur ${\overrightarrow {AB}}$ est bel et bien associé à deux points: son origine A et son extrémité B. Et ses coordonnées se calculent à partir de celles de A et de B:
Ce qui oblige, soit à placer la classe vecteur dans le même fichier, soit à l'importer avec
si on a enregistré ladite classe dans un fichier vector.rb.
Là encore, on parle de méthode vecteur jusqu'à q pour un point p.

## Distance

La distance jusqu'à q est un nombre, mais associé à deux points:
Pour faire le plus simple possible, on a là encore utilisé le fichier des vecteurs sous la forme de sa méthode norme: La distance AB est la norme du vecteur ${\overrightarrow {AB}}$, qu'on calcule avec la fonction hypot de Ruby (voir au chapitre suivant comment on l'utilise).
Pour calculer la distance entre p et q, on entre
ou, au choix,

# Application au problème

Pour récapituler, la classe Point en entier est décrite ici:
C'est tout!
On commence par créer trois points, les sommets du triangle:

## Nature de ABC

Pour voir si ABC est isocèle, on peut afficher les longueurs de ses côtés:
mais on n'apprend pas grand-chose (sinon qu'il n'est pas isocèle). Mais on peut chercher s'il est rectangle avec la réciproque du théorème de Pythagore:
C'est clair, le triangle ABC est rectangle en C.

## Centre du cercle

Il en résulte alors que le cercle circonscrit a pour diamètre [AB], donc pour centre le milieu M de [AB] et pour rayon la moitié de AB:

## Rayon du cercle

Le rayon peut se calculer en divisant par 2 la distance AB, ou mieux, en vérifiant que les trois rayons MA, MB et MC ont la même longueur à la précision permise par Ruby:

## Figure

On peut résumer le tout en modifiant le script ci-dessus pour qu'il crée des éléments svg, dont le résultat est visible ci-dessous:

# Vecteurs en Ruby

Un vecteur peut être défini par ses deux coordonnées ou avec deux points (son origine et son extrémité). La seconde technique a été abordée dans le chapitre précédent; on utilisera donc ici la définition par les coordonnées:

## Définition

Le vecteur sera donc ici une classe Vecteur:
Créer un vecteur, c'est donc lui donner une abscisse et une ordonnée. Comme on l'a vu dans le chapitre précédent, on peut maintenant en créer en Ruby avec

## Coordonnées

On gère les coordonnées et l'affichage comme avec les points; il y a beaucoup de ressemblance entre les vecteurs et les points, ce sont les méthodes qui ne seront pas les mêmes.

### Abscisse

Pour lire ou modifier l'abscisse d'un vecteur u, on invoque u.x.

### Ordonnée
## Affichage

Il suffit pour afficher un vecteur u, de faire

## Norme

La norme d'un vecteur se calcule avec le théorème de Pythagore:
On a utilisé la norme d'un vecteur pour calculer des distances au chapitre précédent.

## Opérations

Il n'est pas d'usage de calculer le milieu de deux vecteurs, mais par contre, on n'additionne pas les points d'habitude (sauf avec GeoGebra). Mais les vecteurs, eux, on les additionne:

### Somme

La somme de deux vecteurs est définie par la somme des coordonnées:
La notation est infixée ce qui fait que la somme de deux vecteurs u et v se note tout simplement u+v.

### Produits

Il y a deux multiplications intéressantes:

#### Par un nombre

En multipliant un vecteur par un nombre, on obtient un vecteur:
Seulement on est obligé de mettre le nombre après le vecteur (u*3 pour avoir le triple de u, alors que d'habitude on fait plutôt le contraire: 3u), et ce produit est moins intéressant que le suivant:

#### Par un vecteur

En multipliant un vecteur par un vecteur, on obtient un nombre. Comme les nombres sont disposés comme les barreaux d'une échelle, on appelle cette multiplication, le produit scalaire des deux vecteurs:
On écrit u*v pour avoir le produit scalaire de u par v.

## Tests
### De colinéarité

Pour savoir si deux vecteurs sont colinéaires, on compare deux produits:
Pour savoir si u et v sont colinéaires, on entre
qui donnera true ou false selon que les vecteurs sont, ou non, colinéaires.

### D'orthogonalité

Pour savoir si deux vecteurs sont orthogonaux, on compare leur produit scalaire à 0:

## Exemple

Dans l'exemple du chapitre précédent, le produit scalaire permet plus rapidement de vérifier que le triangle ABC est rectangle:

# Droites en Ruby

La droite peut être définie à partir d'une de ses équations, mais aussi à partir de deux points. Et comme on a vu précédemment comment on peut créer en Ruby un objet point, on va voir comment on peut s'en servir pour gérer des droites sous Ruby.

## Définition

Là encore, on va définir une classe Droite possédant, lors de son instanciation, deux points:

## Vecteurs
### Vecteur directeur

On obtient le vecteur directeur de d par d.directeur

### Alignement

Pour savoir si le point m est sur la droite d, on peut rajouter ce test:
mais on le rajoute dans l'objet Point, puisque c'est une propriété du point...

### Vecteur normal

Le vecteur normal s'obtient en choisissant ses coordonnées pour que le produit scalaire avec le vecteur directeur soit nul:
Le vecteur normal s'obtient avec d.normal et permet facilement d'avoir l'équation cartésienne ci-dessous.

## Équations
### Équation cartésienne

Pour afficher l'équation cartésienne de d, on entre

### Équation réduite

Comme il y a des divisions à effectuer, on a intérêt à faire appel à mathn':

#### Équation

L'équation réduite se définit par
et s'obtient par d.reduite.

## Comparaison de deux droites
### Parallélisme

Deux droites sont parallèles lorsque leurs vecteurs directeurs sont colinéaires. Mais aussi (sous réserve qu'elles en aient) lorsqu'elles ont le même coefficient directeur:
Pour savoir si deux droites d1 et d2 sont parallèles, on fait

### Perpendicularité

Deux droites sont perpendiculaires si et seulement si leurs vecteurs normaux sont orthogonaux:
On aurait aussi pu chercher si le produit de leurs coefficients directeurs est égal à -1.

### Intersection

Pour calculer les coordonnées du point d'intersection de deux droites, on résout un système.

## Exemple

Dans l'exemple des chapitres précédents, on peut regarder si les deux droites (CA) et (CB) sont perpendiculaires:

# Résolution de problèmes en Ruby

** Systèmes
** Triplets pythagoriciens
** Systèmes congruentiels
** Problème de Freudenthal
** Théorie de Joukovski

# Résolution de systèmes en Ruby

En notant x le prix d'un xylophone et y celui d'un youkoulélé, l'énoncé se traduit algébriquement par 2y=3x+1 et x+y=8.
On va donc voir comment résoudre le système de deux équations à deux inconnues suivant:
$\left\{{\begin{array}{rcl}3x-2y&=&-1\\x+y&=&8\end{array}}\right.$

# Méthode itérative

Dans le cas présent, il se trouve que x et y sont entiers naturels. Si on sait que c'est le cas, on peut les chercher par tâtonnement avec une boucle sur x et sur y. On va successivement fabriquer un tableau bidimensionnel avec les entiers de 0 à 100 (deux premières lignes) puis regarder quels couples de ce tableau vérifient à la fois les deux conditions données par le système:

# Méthode algébrique

Le système $\left\{{\begin{array}{rcl}3x-2y&=&-1\\x+y&=&8\end{array}}\right.$ peut aussi s'écrire matriciellement $\left({\begin{array}{rr}3&-2\\1&1\end{array}}\right)\left({\begin{array}{r}x\\y\end{array}}\right)=\left({\begin{array}{r}-1\\8\end{array}}\right)$ soit $AX=B$ avec $A=\left({\begin{array}{rr}3&-2\\1&1\end{array}}\right)$ et $B=\left({\begin{array}{r}-1\\8\end{array}}\right)$. Alors sa solution $X=\left({\begin{array}{r}x\\y\end{array}}\right)$ s'obtient par le calcul matriciel $X=A^{-1}B$, ce qui se fait directement avec le module matrix de Ruby:
En ayant choisi mathn avec, les solutions s'écrivent automatiquement sous forme de fractions si elles ne sont pas entières.

# Triplets pythagoriciens en Ruby

L'énoncé du problème est simple, sa solution avec Ruby aussi:
Trouver tous les triplets pythagoriciens (x,y,z) tels que $x+y+z=1000$; autrement dit, on demande les triangles rectangles de périmètre 1000 dont les côtés sont entiers.
On apprend qu'il n'y a qu'un triplet de somme 1000.

# Rallye mathématique de la Réunion
## Sujet 2005, Exercice 2

On demande combien d'élèves il y a au total.
On va filtrer les solutions avec les critères donnés par l'énoncé, l'un après l'autre.

### Intervalle

les nombres à tester sont tous les nombres entre 2800 et 2900, il y en a donc 101:

### Par 2

On ne va finalement garder que les nombres qui, pris 2 par 2, laissent 1 (soit tels que le reste de la division par 2 donne 1; on rappelle que ce reste se note par le symbole pourcent).
Ah! Il n'en reste plus que 50 à tester!

### Par 3

Parmi ces 50, on va garder uniquement ceux qui, pris 3 par 3 aussi, laissent 1:
De 50, on est passé à 17.

### Par 4

Ensuite on garde ceux des 17 qui, divisés par 4, laissent 1:
Plus que 8...

### Par 5

On continue l'épuration:
Plus que deux candidats possibles !

### Par 6

Pas de changement, toujours deux candidats.

### Par 7

Maintenant on veut garder les nombres divisibles par 7. Le reste euclidien devra donc être nul:
Et hop! On a le nombre d'élèves!

## Sujet 2007, Exercice 3

Ce soir, veille de marché, il est perplexe.
* S’il met ses œufs dans des emballages de 6, il en reste 2.
* S’il utilise des emballages de 10, il en reste encore 2.
* Il me faudrait, dit-il, des emballages de 8 pour tout contenir exactement.
On demande combien il y a d'œufs en tout.
Même exercice que celui d'au-dessus:

### Par 6

Plus que 27 nombres à tester.

### Par 10

Plus que 5 nombres à tester.

### Par 8

On veut que le reste dans la division par 8 soit nul:
Un seul nombre a réussi le parcours du combattant jusqu'au bout: C'est la solution au problème.

# Freudenthal sous Ruby

Le problème de Freudenthal est intéressant à traiter en Ruby parce qu'il peut se résoudre en manipulant des tableaux et ensembles et que pour Ruby, les tableaux peuvent se manipuler comme des ensembles et vice-versa. Le problème est d'ailleurs intéressant en soi parce qu'il porte sur la logique épistémique. En voici l'énoncé traduit du Néerlandais à l'Anglais puis au Français:
* Polly: Je ne sais pas qui sont x et y.
* Sam: Je savais que tu ne savais pas!
* Polly: Alors je sais qui sont x et y.
* Sam: Alors je sais aussi!
Le but du problème est donc d'utiliser les connaissances qu'on a sur les connaissances de Polly et Sam pour savoir si on peut savoir quels sont x et y.
Il y a de nombreuses méthodes pour y arriver, et Ruby est en quelque sorte un langage "multiparadigme" où chacun peut utiliser sa propre logique (épistémique ou non) pour aborder le problème.

## Digression arithmétique

Si on avait confié un nombre premier à Polly, elle n'aurait pas avoué son impuissance lors de sa première affirmation. Bien que ce ne soit nullement nécessaire pour résoudre ce problème, Ruby sait depuis la version 1.9 manipuler des nombres premiers. Avec
on peut savoir si p est premier, et avec
on décompose n en facteurs premiers.

## Les produits à partir des sommes

Plutôt que de manipuler des couples d'entiers x et y possibles, on va, comme dans la version Python, manipuler l'ensemble des produits possibles. Donc on aura besoin de l'outil permettant, à partir d'une somme s donnée à Sam, d'obtenir la liste prod(s) des produits donnés à Polly qui correspondent aux mêmes x et y:
On peut décrire l'algorithme ci-dessus ainsi:
* On crée un tableau vide t
* Pour chaque nombre entre 2 et n-2, noté provisoirement x, on rajoute le produit de x par son complément à n dans le tableau t
* Quand on a fini, on transforme t en ensemble, en enlevant les doublons.

## Première affirmation

L'affirmation apporte une information: Le produit donné à Polly peut s'obtenir de plusieurs manières, sinon Polly connaîtrait les facteurs. Pour exploiter cette information, on va commencer par fabriquer l'énorme liste des produits possibles, puis ne garder que ceux qui apparaissent au moins deux fois dans la liste:
On ramasse les y entre 3 et 100; pour chacun d'entre eux on ramasse (collect) les x entre 2 et y-1; si la somme x+y est inférieure ou égale à 100, on rajoute le produit dans le tableau produit. Ensuite on constitue pour chaque p de ce tableau, l'ensemble des k égaux à p dans le tableau. Si cet ensemble contient un seul élément, on l'enlève (reject) du tableau des produits:
Ah oui! Il y en a beaucoup qui restent!

## Deuxième affirmation

Si Sam sait que Polly ne sait pas, c'est parce que quelle que soit la décomposition en somme d'entiers de celui qu'on lui a dicté, le produit correspondant est dans la liste précédente. Sinon elle eût pu savoir qui sont x et y, pour ce que Sam en sait! Sam ne va donc garder que les sommes n pour lesquelles la liste prod(n) calculée avec la fonction ci-dessus ne contient que des éléments de la liste polly, donc si leur intersection est égale à prod(n) (en effet $A\subset B\Leftrightarrow A\cap B=A$ dans l'algèbre de Boole des ensembles):
Il reste plutôt peu de sommes possibles:
| 11 | 17 | 23 | 27 | 29 | 35 | 37 | 41 | 47 | 53 |
On sait ce que Sam sait, mais Sam dit "Ça me suffit pas encore!", et nous aussi!

## Troisième affirmation

Si Polly sait maintenant quels sont x et y, c'est que parmi les sommes ci-dessus, il n'y a pas que des doublons (produits communs à plusieurs sommes). Il y a un produit propre à une des sommes de Sam ci-dessus. Pour en savoir plus, Polly va constituer pour chacun des 10 nombres s ci-dessus, la liste de ses produits prod(s), puis chercher tous les nombres communs à au moins deux de ces 10 listes (les doublons). Ruby peut en faire de même, mais après avoir aplati le tableau des prod(s) (qui est un tableau à deux dimensions), et en plaçant dans la liste des doublons, tous les nombres qui apparaissent plus d'une fois dans le tableau des produits:
Ensuite Polly enlève à chaque liste de produits des sommes de sam, les doublons (par une soustraction d'ensembles), et en comptant le nombre d'éléments de chacun des ensembles obtenus,
Polly constate effectivement la présence d'un et un seul singleton:
| 11 | 17 | 23 | 27 | 29 | 35 | 37 | 41 | 47 | 53 |
| 3 | 1 | 3 | 9 | 9 | 10 | 7 | 13 | 13 | 18 |

## Quatrième affirmation

Puisque Sam sait aussi sa somme, on sait que sa somme est 17 et le produit de Polly, 52:

## À la recherche des x et y perdus

Maintenant qu'on connaît la somme et le produit de x et y, il reste à déterminer ceux-ci, ce qui peut se faire en résolvant l'équation du second degré $x^{2}-17x+52=0$ ou par une double boucle:
Les inconnues x et y sont maintenant connues!

# Joukovski et Ruby

L'écoulement d'un fluide autour d'un cylindre est aisé à calculer (par exemple pour étudier l'effet Magnus), et toute transformation conforme permet d'en déduire l'écoulement autour du transformé du cercle (la trace du cylindre). En particulier lorsque le transformé a la forme d'une aile d'avion, ce qui est le cas avec la transformée de Joukovski. Ce calcul sera effectué par Ruby grâce à ses nombres complexes, puis affiché en fabriquant une figure svg. En fait:
* On utilise l'inverse de la transformée de Joukovski pour calculer l'écoulement autour du cercle unité.
* On agrandit légèrement ce cercle pour qu'il ait une transformée de Joukovski plus intéressante;
* On applique au nouveau cercle la transformée de Joukovski: On a l'écoulement autour de l'aile.
C'est la méthode utilisée par Nikolaï Joukovski au début du vingtième siècle pour les premières études sur l'aéronautique.

# Du cercle au segment

Pour calculer l'écoulement autour du cercle unité, il suffit de trouver une transformation conforme qui transforme un segment (dont l'écoulement est trivial) en le cercle unité. Or l'image d'un point quelconque e$^{it}$ du cercle unité par la transformée de Joukovski $z\mapsto z+{\frac {1}{z}}$ est e$^{it}$+e$^{-it}$=2 cos(t): La transformation de Joukovski J(z) transforme le cercle unité en le segment [-2;2].
Et l'écoulement autour du segment est le plus simple possible, puisque c'est comme si le segment n'était pas là: Des droites verticales représentent les équipotentielles (ou isobares), et des droites verticales représentent les lignes de courant (ou écoulement) qui montrent la vitesse du vent. La transformation conforme qui produit cette grille est la transformation identique id(z)=z.

# Du segment au cercle
## Transformée inverse

Il suffit donc d'appliquer à cet écoulement l'inverse J$^{-1}$ de la transformée de Joukovski, qui envoie le segment [-2;2] sur le cercle unité. Or J$^{-1}$ est multiforme. On utilisera donc la fonction fplus valant $f_{plus}(z)={\frac {z+{\sqrt {z^{2}-4}}}{2}}$ sur la moitié droite de l'image, et la fonction fmoins valant $f_{moins}(z)={\frac {z-{\sqrt {z^{2}-4}}}{2}}$ sur la moitié gauche. Ces fonctions sont complexes:
Le paramètre R est un facteur d'échelle permettant de zoomer sans avoir à refaire tout le script.
La figure est enregistrée dans un fichier au format svg appelé JoukovskiRuby1.svg:
La figure occupera donc 640 pixels de large et 480 pixels de haut, et s'appellera figure tout simplement.

## Tracé des isobares
### Côté droit de la figure

Pour tracer les isobares, on prend un point d'affixe x-2i et on le transforme par J$^{-1}$. Puis on commence un path de svg par ce point. Ensuite on transforme des points situés sur la même droite verticale que le premier point choisi, et on les ajoute au path (une chaîne de caractères appelée ligne). La courbe obtenue (le path) sera en jaune et est inscrite à la fin dans le fichier:

### Côté gauche de la figure

Les isobares de gauche se dessinent de la même manière, en remplaçant fplus par fmoins:

## Tracé des lignes de courant

Pour les mettre en exergue, on fera les lignes de courant en rouge.

### Côté gauche de la figure

Il suffit d'intervertir les rôles de i (abscisse) et j (ordonnée):
Le décalage des abscisses permet d'éviter le passage par l'origine, où le changement de feuillet de la transformation donnerait des résultats graphiquement bizarres.

### Côté droit de la figure

Même principe, en remplaçant fmoins par fplus:

## Tracé du cercle

Pour ajouter le cercle lui-même sur la figure, on peut utiliser l'objet circle de svg; on en profite pour fermer la bannière svg et clore le fichier:
C'est tout ce qu'il faut pour obtenir l'écoulement que voici:
Le défaut des isobares en-dessous du cercle (la figure aurait dû être symétrique par rapport à l'axe des abscisses) est lié au changement de feuillet de J$^{-1}$. Pour y remédier, on peut remplacer la moitié du bas par la symétrique de la moitié du haut, ce qui double la longueur du script (une fonction par quadrant). La correction est laissée en exercice.

# Conception de l'aile d'avion

Si on applique à la figure ci-dessus (avec le cercle unité), la transformation J(z), on obtient l'écoulement autour de [-2;2] qui est trivial. Mais on peut modifier le cercle pour qu'il passe toujours par le point d'affixe 1, et la transformée de Joukovski du nouveau cercle aura toujours un point de rebroussement d'affixe 2, mais peut avoir une forme de lemniscate, ou de profil d'aile d'avion, selon le paramètre choisi.

## Tracé du profil

Une fonction affine complexe laisse le point d'affixe 1 invariant, si elle est de la forme fa(z)=P(z-1)+1. Le meilleur moyen de choisir la valeur du coefficient directeur P est d'implémenter fa et J avec un logiciel de géométrie dynamique (par exemple, CaRMetal qui exporte au format svg), et de bouger le point d'affixe P avec la souris jusqu'à ce que l'image du cercle par J(fa(z)) ait la forme voulue:
Le choix de P=0,93+0,15i paraît satisfaisant.

## Calcul de l'écoulement

Pour la fonction de Joukovski, on ajoute un très petit nombre à z pour que le nombre zéro passe entre les mailles du filet, ce qui évite le risque d'avoir une erreur de division par zéro. À part ça, il suffit d'appliquer J(fa(z)) au cercle unité, et de remplacer le cercle final par son image par J(fa(z)) (pour dessiner l'aile). Ce qui donne le script suivant:

## Figure obtenue

L'exécution du script produit la figure suivante:
Le fait que les lignes de courant sont plus courbées sur le dessus que sur le dessous entraîne par la force de Bernoulli, une dépression sur le dessus de l'aide, qui est à l'origine de la portance: L'avion vole!