niveau d'indentation 0 |
On peut
x
pour un texte).svg
En coffeescript, l'affectation est notée par un "=".
Par exemple,
x = 2
x = x+1
Une variable peut être affectée par un nombre mais aussi par du texte, une liste ou même une fonction.
On peut affecter simultanément a par 1 et b par 2 avec
[a,b] = [1,2]
Pour augmenter x de 1, on peut faire indifféremment
x = x+1 x += 1 x++
Pour faire entrer un nombre x par l'utilisateur, il faut affecter x (donc écrire un signe "égal") et afficher un message d'invite rappelant ce que représente le nombre. Par exemple
x = entre "Allo non mais allo quoi! Tu veux mettre quoi dans x ?"
Tant qu'on ne demande pas à CoffeeScript d'afficher le résultat d'un
calcul, on ne peut pas connaître celui-ci. Il y a deux moyens de faire
connaître le contenu de x
:
alerte x
x
dans le cadre prévu à cet effet à droite
de la page avec
affiche x
Pour lancer un dé à 6 faces
affiche dé 6
Le nombre de faces doit être en entier, sans limite.
Pour vérifier, on peut lancer 10 fois le dé:
(dé 6 for n in [1..10])
Pour jouer à pile ou face, on lance un dé à deux faces.
affiche alea()
donne un nombre aléatoire entre 0 et 1
On peut alors simuler une variable aléatoire Z normale centrée (d'espérance 0) et réduite (d'écart-type 1) avec
Z = -6 for n in [0...12] Z += alea() affiche Z
Essayer par exemple
gauss = () -> Z = -6 Z += alea() for n in [0...12] Z grosTableau = (gauss() for n in [1..1000]) histogramme grosTableau, -3, 3, 15, 200
Pour tester l'égalité entre deux objets, il y a deux manières:
2+2 == 4
2+2 is 4
affiche 2+2 is 5
affiche false
(ben oui!)
Pour obtenir le contraire d'une proposition, la précéder par un point d'exclamation
affiche not 2+2==5 affiche 2+2 isnt 5
Le symbole "≠ se note donc isnt
ou !=
, au choix.
Pour dire que x est à la fois positif et pair, on peut écrire
x > 0 and x%2 is 0
Pour dire que x est, ou bien positif, ou bien pair (ou les deux), on peut écrire
x > 0 or x%2 is 0
Une alternative est le double trait vertical.
Pour taper le symbole "trait vertical", appuyer avec la main droite sur et, sans lâcher ce bouton, actionner le en haut du clavier, de la main gauche.
Un test est une instruction conditionnelle; Pour n'effectuer quelque chose que lorsqu'une condition est vraie (par exemple seulement si le dé est tombé sur 6), faire
if dé(6) is 6 affiche "gagné"
On remarque l'indentation qui précise que la partie
affiche "gagné"
ne doit s'effectuer que si le dé vaut 6.
affiche "gagné" if dé(6) is 6
a le même effet.
Que faire quand le dé ne tombe pas sur 6 ?
Si on ne s'intéresse pas au gain mais seulement à la défaite, on est pessimiste et on écrit
affiche "perdu" unless dé(6) is 6
Mais les deux cas peuvent être traités ensemble:
if dé(6)==6 affiche "gagné" else affiche "perdu"
On peut aussi faire un test dans un intervalle:
(x for x in [1..12] when x%2==0)
En CoffeeScript, les intervalles sont composés uniquement d'entiers.
L'intervalle fermé [a;b] se note [a..b] avec deux points;
L'intervalle ouvert à droite [a;b[ se note [a...b] avec trois points;
L'appartenance se note in
;
Pour vérifier que 2 est compris entre 0 et 5:
affiche 2 in [0..5] affiche 0 <= 2 <= 5
L'appartenance est aussi utilisée pour appliquer une fonction à un intervalle:
affiche (x*x for x in [0..5])
Pour ajouter un élement x à un ensemble A:
A.push x
Pour enlever le nombre 5 d'un ensemble A:
A = (x for x in A if x isnt 5)
L'intersection de deux ensembles A et B est formée des x de A qui sont aussi dans B:
I=(x for x in A when x in B)
Une légère différence mais qui change tout:
(x for x in A when x not in B)
est le complémentaire de B dans A.
En probabilités, cette notion formalise le contraire d'un évènement.
La réunion de deux intervalles n'est pas nécessairement un intervalle:
A=(x for x in [0..100] when 2 < x < 15 or 80 <= x < 90) affiche A
À la différence d'un ensemble, un multiensemble (ou sac) peut contenir plusieurs occurences d'un élément. On crée un sac à partir d'un tableau, on ajoute un élément dans un sac comme dans un ensemble, mais on peut aussi ajouter plusieurs fois un élement d'un coup. Ainsi, pour créer une urne contenant 7 boules rouges et 3 boules bleues, on peut faire, ou bien
urne = new Sac ['rouge','rouge','rouge','rouge','rouge','rouge','rouge','bleu','bleu','bleu']
ou bien
urne = new Sac [] urne.ajoute 'rouge' for n in [1..7] urne.ajoute 'bleu' for n in [1..3]
ou enfin
urne = new Sac [] urne.ajouteFois 7, 'rouge' urne.ajouteFois 3, 'bleu'
On peut calculer les intersection et réunion de deux multiensembles comme pour les ensembles,
oter un élément d'un multiensemble avec .ote élément
ou extraire un élément au hasard d'un multiensemble;
comme pour un ensemble, le cardinal d'un multiensemble est le nombre d'éléments (comptés
avec leur multiplicité) qu'il contient. sac.contient x
teste si l'élément x
se trouve ou non dans le sac.
Si on divise 0 par 0 on obtient NaN
(not a number) qui signifie que la division n'a pas de sens.
Mais si on divise 1 (ou tout autre nombre non nul) par 0,
on obtient Infinity
, ce qui veut dire que lorsqu'une variable x
tend vers 0, son inverse 1/x tend vers l'infini;
De même,
1/Infinity
donne 0: Si une variable x tend vers l'infini, son inverse 1/x tend vers 0.
affiche Infinity+Infinity
La somme de deux fonctions qui tendent vers +∞ tend elle-même vers +∞
affiche 3+Infinity
La somme d'une fonction qui tend vers 3 et d'une fonction qui tend vers +∞ tend elle-même vers +∞
affiche Infinity-Infinity
On ne peut rien conclure sur la somme d'une fonction qui tend vers +∞ et d'une fonction qui tend vers -∞: Il s'agit d'une forme indéterminée.
affiche Infinity*Infinity
Le produit de deux fonctions qui tendent vers +∞ tend lui-même vers +∞
affiche 3*Infinity
Le produit d'une fonction qui tend vers 3 et d'une fonction qui tend vers +∞ tend lui-même vers +∞
affiche 0*Infinity
On ne peut pas conclure sur le produit d'une fonction qui tend vers ∞ et d'une fonction qui tend vers 0: Il s'agit d'une forme indéterminée.
affiche leLogarithmeDe 0 affiche leLogarithmeDe Infinity
La limte de ln en 0 est -∞ et la limite de ln en +∞ est +∞
affiche exp -Infinity affiche exp Infinity
La limite de ex est 0 lorsque x tend vers -∞ et +∞ lorsque x tend vers +∞.
Une fonction associe à une variable d'entrée (ou plusieurs) appelée antécédent, une (ou plusieurs) variable de sortie appelée image; l'image de x par la fonction f est notée f(x); Aussi, en CoffeeScript, une fonction est-elle désignée par une flèche -> séparant l'antécédent, entre parenthèses, de l'image, qui est une expression. Après la flèche on peut insérer un algorithme destiné à calculer la fonction par algorithme.
La dernière ligne écrite dans la fonction est la valeur retournée.
Une fonction peut ne pas avoir d'antécédent, dans ce cas c'est une procédure.
(x) -> 3
est une fonction constante.
(x) -> x/2+1
est une fonction affine.
On peut affecter une variable par une fonction comme dans
f = (x) -> x*x-2*x-1
Ensuite on peut entrer f(3)
ou f 3
pour avoir l'image de 3 par f.
Parmi les fonctions prédéfinies, on trouve
sinus
et cosinus
en degrés (pour l
es radians, utiliser sin
et cos
)laRacineDe
pour la racine carrée; leCarréDe
,
leCubeDe
pour le carré et le cube d'un nombre;
lInverseDe
pour l'inverse d'un nombre (1 divisé par ce nombre)leLogarithmeDe
pour le logarithme népérien, et
lExponentielleDe
pour ex.Pour avoir un tableau de valeurs d'une fonction, on peut construire un tableau associatif dans lequel on associe à chaque valeur de x choisie, son image par la fonction. Ensuite on peut afficher ce tableau associatif dans le tableau ci-dessus ("sorties graphiques")
tableauAssoc = {} for x in [1,2,3,5,10] tableauAssoc[x] = leCarréDe x trierDansTableau tableauAssoc
Plus court: On peut afficher les x et leurs images dans l'affichage:
for x in [1,2,3,5,10] affiche "#{x}, #{leCarréDe x}"
Ensuite, on sélectionne à la souris les nombres, et on les copie-colle dans un fichier portant l'extension "csv" (par exemple carré.csv); il suffit ensuite d'ouvrir ce fichier avec un tableur pour avoir non seulement le tableau, mais aussi la représentation graphique.
Pour répéter 10 fois une action, on a besoin d'une variable appelée indice de la boucle. Ici on notera i cet indice, qui ira de 1 à 10.
Par exemple, pour lancer un dé 10 fois, on peut entrer
for i in [1..10] affiche dé 6
Un bon moyen de suivre l'indice d'une boucle est d'afficher celui-ci dans la boucle:
for in in [1..10] affiche i
affiche i for i in [1..10]
a le même effet...
Les nombres 1, 2, 3 etc parcourus forment une suite arithmétique de raison 1.
Pour faire descendre l'indice (compte à rebours) on peut faire
affiche i for i in [10..1]
Pour aller de 3 en 3 on peut faire
affiche i for i in [1..10] when i%3 is 1
ou, mieux:
affiche i for i in [1..10] by 3
Pour boucler sur les nombres premiers inférieurs à 20:
for i in [2,3,5,7,11,13]
Pour lancer un dé jusqu'à ce qu'on ait un 6 (et compter les lancers dans un indice i), on fait
i=0 i++ until dé(6) is 6
Il y a plusieurs manières de faire ça; par exemple
i=1 i++ while dé(6) isnt 6
On peut aussi faire comme ceci:
i=1 while dé(6) isnt 6 i=i+1
Un dé icosaédrique, comme son nom l'indique, a 20 faces numérotées de 1 à 20. L'univers de probabilité est alors Ω={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; On peut le calculer en fabricant un ensemble à partir de la liste des nombres allant de 1 à 20 :
univers = new Ensemble [1..20] affiche univers
L'évènement «le résultat est pair» s'écrit A={2,4,6,8,10,12,14,16,18,20}; il peut se définir en compréhension par
A = new Ensemble (x for x in univers.support when x%2 is 0)
L'évènement «le résultat s'écrit avec un seul chiffre» peut se définir de façon analogue mais aussi en faisant comme pour l'univers; on obtient B={1,2,3,4,5,6,7,8,9}
B = new Ensemble [1..9]
Le contraire de A est formé des résultats qui sont dans l'univers mais pas dans A; on l'obtient par
A.complémentDans univers
L'évènement «le résultat est pair, et en plus il s'écrit avec un seul chiffre», noté A ∩ B, s'obtient par
A.inter B
L'évènement «le résultat est pair, ou alors il s'écrit avec un seul chiffre (à moins que ce soit les deux en même temps)», noté A ∪ B, s'obtient par
A.union B
Pour chercher les nombres premiers inférieurs ou égaux à 200, on peut faire ainsi :
crible = new Ensemble [1..200] for m in [2..200] poubelle = new Ensemble (x for x in crible.support when x>m and x%m is 0) crible = poubelle.complémentDans crible affiche crible
En fait, on peut aussi implémenter cet algorithme avec des tableaux, ce qui permet alors d'afficher l'histogramme des nombres premiers :
N = 200 crible = [2..N] for m in [2..N] poubelle = (x for x in crible when x>m and x%m is 0) crible = (x for x in crible when x not in poubelle) histogramme crible, 0, 200, 10, 10
Le nombre d'éléments que contient un ensemble est son cardinal; pour savoir combien d'éventualités se trouvent dans A, on fait
A.cardinal()
Si son cardinal est nul, A est l'évènement impossible (le contraire de l'univers); pour savoir si un ensemble est vide, on fait
A.estVide()
La probabilité d'un évènement A est définie comme le quotient de son cardinal par celui de l'univers; elle dépend donc du choix de l'univers, et se note PΩ(A), ou, lorsqu'il n'y a pas d'ambigüité sur Ω, simplement P(A):
univers = new Ensemble [1..20] proba = (E) -> E.probaSachantQue univers B = new Ensemble [1..9] affiche proba(B)
La sortie graphique mesure 640 pixels de large et 480 pixels de haut. Les abscisses vont donc de 0 (tout à gauche) jusqu'à 640 (tout à droite); mais les ordonnées sont ordonnées de haut en bas: 0 pour un élement graphique tout en haut, et 480 pour un élément graphique tout en bas.
Pour effacer le dessin, on entre
effaceDessin()
Pour exporter le dessin :
$("#sortieSVG").text $("#graphique").html()
Ensuite, copier-coller le contenu du champ texte qui est en-dessous du graphique,
vers un éditeur de texte; sauvegarder le résultat avec une extension .svg
.
On dessine un point comme un cercle de rayon petit, par exemple
dessineCercle 240, 100, 2, 'red'
pour dessiner le point de coordonnées (240,100) (représenté comme un cercle de rayon 2 pixels).
Pour dessiner le segment joignant les points de coordonnées respectives (100, 200) et (400, 300) :
dessineSegment 100, 200, 400, 300, 'blue'
Pour dessiner le rectangle dont le coin supérieur gauche a pour coordonnées (200,50) et de largeur 40 pixels, et de hauteur 150 pixels:
dessineRectangle 200, 50, 40, 150, 'cyan'
Pour écrire sur le graphique (aux coordonnées (150,100) ici), on fait
dessineTexte "alcoffeethmique Mac", 150, 100, 'grey'
On peut choisir la couleur que l'on veut pour chacune de ces primitives graphiques
Pour dessiner un polygone, il faut lui fournir la liste des coordonnées de ses sommets
(chacun des éléments de cette liste est lui-même une liste de deux nombres), ainsi que la couleur
du périmètre et celle du remplissage (none
si on ne veut pas remplir)
dessinePolygone [[20,240],[600,20],[600,460]], 'black', 'yellow'
Pour dessiner l'axe gradué des abscisses allant de -1 à 3, en mauve :
dessineAxeX -1, 3, 'magenta'
et de façon similaire pour l'axe des ordonnées (dessineAxeY
); on peut
dessiner d'un coup les deux axes avec
dessineAxes -1, 3, -10, 100, 'brown'
Ces fonctions sont utilisées dans les deux suivantes:
Pour représenter graphiquement la fonction carré
sur [-10,10] :
dessineFonction carré, -10, 10, 0, 100, 'red'
Pour représenter graphiquement une suite, il faut la calculer comme une liste de nombres;
par exemple, pour représenter graphiquement la somme des n
premiers entiers
(c'est une suite d'entiers) pour n
allant de 0 à 10, avec des points de rayon
3, en bleu :
dessineSuite (laSommeDe [1..k] for k in [0..20]), 10, 0, 60, 3, 'blue'
diagrammeBatons {'pour': 25, 'contre': 60, 'sans opinion': 15}, 100
Le second paramètre est un facteur d'échelle sur l'axe des ordonnées
Variante si le caractère est quantitatif:
lancers = new Sac [] lancers.ajoute dé(6) for n in [1..100] diagrammeBatonsTrie lancers.effectifs , 40
Pour dessiner un histogramme, il faut une liste de nombres, les bornes d'un intervalle et le nombre de rectangles :
carrés = (x*x for x in [0..100]) histogramme carrés, 0, 10000, 10, 40
Pour faire des statistiques sur une liste, il est parfois nécessaire de la trier (par exemple, pour calculer les quantiles). Comme "trier" se dit "sort" en anglais, on trie la liste L ainsi:
L.sort (x,y)->(x > y)
L.sort (x,y)->(x < y)
Math.max.apply null,L Math.min.apply null,L
Pour connaître l'effectif total d'une liste, on peut utiliser sa "longueur" (en anglais, length):
L.length
laSommeDe L
laMoyenneDe L
laVarianceDe L
lEcartTypeDe L
laMédianeDe
Personne ne sait encore si cet algorithme s'arrête au bout d'un temps fini pour toute valeur initiale entière u0:
u = 35 until u is 1 if u%2 is 0 u /= 2 else u = 3*u+1 affiche u
u = 35 Collatz = [u] until u is 1 if u%2 is 0 u /= 2 else u = 3*u+1 Collatz.push u Syr = {} for n in [0...Collatz.length] Syr[n]=Collatz[n] trierDansTableau Syr dessineSuite Collatz, Collatz.length-1, 0, 200, 3, 'red'
vol = (n) -> [u, temps] = [n, 0] until u is 1 if u%2 is 0 u /= 2 else u = 3*u+1 temps++ temps affiche (vol n for n in [2..20])
Pour calculer le pgcd de deux nombres a et b, on remplace a et b par b et r jusqu'à ce que r soit nul (r est le reste de la division de a par b).
pgcd = (a,b) -> [x,y]=[a,b] while y>0 [x,y]=[y,x%y] x affiche pgcd 55,34
pgcd = (x,y) -> while y>0 [x,y]=[y,x%y] x affiche pgcd 55,34
Pour calculer la racine carrée de 5 par l'algorithme de Heron, on remplace une valeur approchée a (par défaut), par sa moyenne avec 5/a (valeur approchée par excès); et on recommence jusqu'à ce que la différence entre les valeurs approchées par défaut et par excès soit devenue imperceptible.
[a,b]=[1,5] until (abs b-a)<1e-16 a=(a+b)/2 b=5/a affiche a
En plaçant les approximations successives de √(2) dans un tableau, on peut les représenter graphiquement, pour vérifier la convergence :
u=[1] for n in [1..20] u[n]=(u[n-1]+2/u[n-1])/2 dessineSuite u, 20, 0, 2, 5, 'red'
L'algorithme de Heron, appliqué à de grands nombres décimaux, permet de calculer 1000 décimales de √(5) :
Big.DP = 1000 [a,b]=[Big(1),Big(5)] for n in [1..12] a=a.plus(b).div(2) b=Big(5).div(a) affiche a
Pour trouver combien de fois il a fallu boucler, une méthode simple est de faire des
essais en affichant affiche a.minus b
jusqu'à ce que l'affichage donne 0.
La méthode suivante est plus rapide :
Big.DP = 1000 a = Big(5).sqrt() affiche a
Cette rapidité permet d'ailleurs de faire une étude statistique sur les décimales de √(5), mais ceci est une autre histoire :
Le graphique ayant été obtenu avec ce script :
Big.DP = 1000 a = Big(5).sqrt() décimales = a.toString()[2..] stats = new Sac [] for x in décimales stats.ajoute parseInt(x) diagrammeBatonsTrie stats.effectifs, 150
racineDe = (x) -> [a,b]=[1,x] until (abs b-a) < 1e-16 a=(a+b)/2 b=x/a a affiche racineDe 5
La différence entre racineDe(x)
et la "vraie" racine carrée de x dépend
fortement de x :
racineDe = (x) -> [a,b]=[1,x] until (abs b-a) < 1e-5 a=(a+b)/2 b=x/a a erreur = (x) -> racineDe(x) - racine(x) dessineFonction erreur, 0.1, 20, 0, 1e-5, 'blue'
au degré près:
arr3 = (x) -> arrondi(1000*x)/1000 affiche "|angle|sinus|" affiche "|#{n} |#{arr3 sinus n} |" for n in [0..90]
à la minute près:
arr3 = (x) -> arrondi(1000*x)/1000 affiche "|angle|sinus|" affiche "|#{arr3 n} |#{arr3 sinus n} |" for n in [0..1] by 1/60
Remarque: On peut aussi faire
tableauValeurs sinus, [0..20]
arr3 = (x) -> arrondi(1000*x)/1000 affiche "|angle|cosinus|" affiche "|#{n} |#{arr3 cosinus n} |" for n in [0..90]
L'algorithme de dichotomie est efficace pour résoudre l'équation f(x)=0
f = (x) -> ln(x) - 1 [a,b]=[1,10] until b-a < 0.000001 m=(a+b)/2 if f(m)<0 a=m else b=m affiche [a,b]
Résoudre une équation, c'est donner la liste de ses solutions; pour le second degré, il y a 0, 1 ou 2 solutions selon le signe du discriminant Δ :
SecondDegré = (a,b,c) -> S=new Ensemble [] Delta = b*b-4*a*c r = laRacineDe Delta if r >=0 S.ajoute (-b-r)/(2*a) S.ajoute (-b+r)/(2*a) S affiche SecondDegré 1, 2, 1
Combien de fois faut-il lancer un dé équilibré pour que la probabilité d'avoir un 6 dépasse 0,99 ?
La condition de sortie se traduisant par le fait que la probabilité de ne pas avoir de 6 est en-dessous de 0,01; et comme si les lancers sont indépendants, cette probabilité suit une suite géométrique de raison 5/6:
proba = 1 nombreDeLancers=1 until proba < 0.01 proba *= 5/6 nombreDeLancers++ affiche "En lançant #{nombreDeLancers} fois le dé, la probabilité d'avoir un 6 est #{1-proba}"
On construit une liste (ou tableau) des termes successifs de la suite, pour représenter
graphiquement celle-ci. On remarque comme comme sa raison est inférieure à 1, la valeur
maximale est 1; donc on choisit 0 pour yMin
et 1 pour yMax
:
u=[1] for n in [1..20] u[n]=5/6*u[n-1] dessineSuite u, 20, 0, 1, 5, 'red'
Algorithme de Briggs pour calculer des logarithmes
log = (x) -> if x > 0 [r,n]=[x,0] until 0.999999 < r < 1.000001 n++ r=racine r r -= 1 r *= 2 for k in [1..n] r affiche log 2.7182818
En calculant un logarithme par l'algorithme de Briggs, on commet une erreur d'approximation (la différence entre log(x) et ln(x)) qui dépend de x; sa représentation graphique permet de voir comment :
log = (x) -> if x > 0 [r,n]=[x,0] until 0.999999 < r < 1.000001 n++ r=racine r r -= 1 r *= 2 for k in [1..n] r erreur = (x) -> log(x)-ln(x) dessineFonction erreur, 0.1, 10, 0, 0.000002, 'blue'
La suite Fn est définie par la relation de récurrence Fn+2=Fn+1+Fn. Si F0=F1=1, la suite est entièrement déterminée.
[a,b]=[1,1] for n in [1..10] [a,b]=[a+b,a] affiche "F(#{n})=#{b}"
nombreDor = (1 + racine 5)/2 for n in [1..10] b = puissance nombreDor, n b /= racine 5 b = arrondi b affiche "F(#{n})=#{b}"
Pour représenter graphiquement la suite de Fibonacci, on met ses termes successifs dans un tableau. Ce qui revient à les pousser l'un après l'autre dedans :
u=[1,1] for n in [2..30] u[n]=u[n-2]+u[n-1] dessineSuite u, 10, 0, 100, 5, 'red'
Lorsque Galilee lui donnait des cours, Cosme de Medicis, futur Grand-Duc de Toscane, lui a demandé comment ça se fait que lorsqu'on additionne les résultats de 3 dés, le 10 sort plus souvent que le 9, alors que
stats = new Sac [] for n in [1..100000] stats.ajoute dé(6)+dé(6)+dé(6) trierDansTableau stats.effectifs diagrammeBatonsTrie stats.effectifs, 20000
loi = new Sac [] loi.ajoute(a+b+c) for a in [1..6] for b in [1..6] for c in [1..6] d = puissance 6, 3 affiche "La probabilité d'avoir un 9 est #{loi.effectifs[9]/d}" affiche "La probabilité d'avoir un 10 est #{loi.effectifs[10]/d}"
Dans une lettre à Blaise Pascal, le Chevalier de Méré
lui a posé la question suivante: Comment se fait-il qu'en lançant
4 dés, on a plus d'une chance sur 2 d'avoir au moins un 6 ?
gains=0 for n in [1..100000] jeu=(dé(6) for n in [1..4]) if (x for x in jeu when x is 6).length gains++ affiche gains/100000
gains=0 for a in [1..6] for b in [1..6] for c in [1..6] for d in [1..6] if a is 6 or b is 6 or c is 6 or d is 6 gains++ d = puissance 6,4 affiche gains/d
Comme la probabilité de ne pas avoir de 6 en lançant un dé est 5/6, et par indépendance des lancers de dés, la probabilité de na pas avoir de 6 en lançant 4 dés est le quatrième terme d'une suite géométrique de premier terme 5/6 et de raison 5/6:
u = 1 (u *= 5/6 for n in [1..4]) affiche 1-u
Au jeu de Dada (ou des "petits chevaux") on lance un dé jusqu'à ce qu'on ait un 6. Alors seulement, le petit cheval peut "sortir de l'écurie" (on peut commencer à jouer)
La variable aléatoire "nombre de fois qu'on doit lancer le dé pour avoir un 6" suit une loi géométrique de paramètre 1/6. Pour la simuler:
X = 0 X++ until dé(6) is 6 affiche X
Pour jouer plusieurs fois aux petits chevaux, on peut refaire tout ça dans une boucle; on en profite pour faire un tableau d'effectifs:
stats = new Sac [] for n in [1..100] X = 0 X++ until dé(6) is 6 stats.ajoute X trierDansTableau stats.effectifs diagrammeBatonsTrie stats.effectifs, 20
La probabilité que l'algorithme précédent s'arrête au bout d'un temps fini est 1. Néanmoins, on prend moins de risque à tronquer X, en remplaçant tous les X supérieurs à 20 par des 0:
stats = new Sac [] for n in [1..100] X = 0 X++ until dé(6) is 6 X = 0 if X > 20 stats.ajoute X trierDansTableau stats.effectifs diagrammeBatonsTrie stats.effectifs, 20
Tirer 5 cartes (une "main") dans un jeu de 32 cartes, c'est constituer un échantillon d'effectif 5 dans une population totale de 32. C'est donc la base de la statistique.
On vérifie que les 4 couleurs sont équiprobables :
couleur=['♦','♥','♠','♣'] urne = new Sac urne.ajoute prendreAuHasardDans couleur for n in [1..1000] mettreDansTableau urne.effectifs diagrammeBatons urne.effectifs
Les 4 couleurs ont bien l'air équiréparties :
Si on répète 5 fois l'expérience de tirer une carte, on risque d'avoir plusieurs fois la même carte (tirage avec remise). Mais ce risque est minime:
couleur=['♦','♥','♠','♣'] valeur=['1','7','8','9','10','V','D','R'] jeu=[] for c in couleur for v in valeur jeu.push "#{v}#{c}" main = tirageAvecRemise 5, jeu affiche main
couleur=['♦','♥','♠','♣'] valeur=['1','7','8','9','10','V','D','R'] jeu=[] for c in couleur for v in valeur jeu.push "#{v}#{c}" main = tirageSansRemise 5, jeu affiche main
Cas particulier: Pour mélanger le jeu, on fait un tirage sans remise de 32 cartes :
couleur=['♦','♥','♠','♣'] valeur=['1','7','8','9','10','V','D','R'] jeu=[] for c in couleur for v in valeur jeu.push "#{v}#{c}" affiche mélangée jeu
Pour savoir quelle est la probabilité d'avoir un carré d'as,
casPossibles = combinaison 32, 5 casFavorables = combinaison 28, 1 affiche casFavorables/casPossibles
La loi B(10,0.7) est la loi du nombre de boules rouges dans un tirage (avec remise) dans une urne contenant 70 % de boules rouges.
On peut utiliser deux sacs:
urne
, contient les boules rouges et bleues: C'est l'urne !stats
, contient les effectifs des nombres de boules rouges
obtenues dans 100 tirages avec remise de 10 boules extraites du sac précédent.urne = new Sac [] urne.ajouteFois 70, 'rouge' urne.ajouteFois 30, 'bleu' stats = new Sac [] stats.ajoute (urne.extraireAuHasard() for n in [1..10]).compteLes 'rouge' for n in [1..1000] trierDansTableau stats.effectifs diagrammeBatonsTrie stats.effectifs
Pour afficher les valeurs prises par la loi binomiale de paramètres 10 et 0,7 (les probabilités), on peut faire
affiche (binomiale 10, 0.7, k for k in [0..10])
En tirant 200 boules (avec remise) dans une urne contenant 70 % de boules rouges, un intervalle de fluctuation à 95 % pour le nombre de boules rouges parmi les 200 s'obtient par
affiche IntFluctBinom 200, 0.7
Pour calculer un intervalle de confiance sur une proportion p, on utilise de l'algorithmique "de base" (pas de boucles): Affectations, entrées, sorties et éventuellement un test si on veut améliorer.
Cet algorithme simplifié est vu en Seconde et en Terminales L/ES et S
N = entre "Quelle est la taille de l'échantillon ?" ns = entre "Combien de succès dans l'échantillon ?" p = ns/N borneInférieure = p-1/laRacineDe N borneSupérieure = p+1/laRacineDe N affiche "L'intervalle de confiance à 95 % est [#{borneInférieure};#{borneSupérieure}]"
Deux problèmes peuvent se poser:
N = entre "Quelle est la taille de l'échantillon ?" ns = entre "Combien de succès dans l'échantillon ?" p = ns/N borneInférieure = p-1/laRacineDe N borneInférieure = 0 if borneInférieure < 0 borneSupérieure = p+1/laRacineDe N borneSupérieure = 1 if borneSupérieure > 1 if N > 24 affiche "L'intervalle de confiance à 95 % est [#{borneInférieure};#{borneSupérieure}]"
Cet algorithme, plus précis notamment lorsque la proportion de succès dans l'échantillon est proche de 0 ou de 1, est au programme des Terminales STL/STI2D et des BTS :
N = entre "Quelle est la taille de l'échantillon ?" ns = entre "Combien de succès dans l'échantillon ?" p = ns/N q = 1-p borneInférieure = p-1.96*racine(p*q/N) borneSupérieure = p+1.96*racine(p*q/N) affiche "L'intervalle de confiance à 95 % est [#{borneInférieure};#{borneSupérieure}]"
Cette fois-ci, la formule n'est appliquée que si (avec les notations de l'algorithme), N×p et N×q sont tous les deux supérieurs à 5. De plus, l'échantillon doit être suffisamment grand (N≥25):
N = entre "Quelle est la taille de l'échantillon ?" ns = entre "Combien de succès dans l'échantillon ?" p = ns/N q = 1-p borneInférieure = p-1.96*racine(p*q/N) borneSupérieure = p+1.96*racine(p*q/N) if N > 25 and N*p > 5 and N*q > 5 affiche "L'intervalle de confiance à 95 % est [#{borneInférieure};#{borneSupérieure}]" else affiche "Il n'est pas raisonnable de calculer un intervalle de confiance dans ces conditions"
for n in [1..100] x1 = 100+4*n y1 = 440 x2 = 100 y2 = 40+4*n dessineSegment x1, y1, x2, y2, 'black'
sommets = [] for n in [0...17] angle = n*8/17*360 sommets.push [320+200*cosinus(angle),240+200*sinus(angle)] dessinePolygone sommets, 'blue', 'green'
N = 24 for n in [0...N] angle = n/N*360 cx = 320 + 100*cosinus(angle) cy = 240 + 100*sinus(angle) dessineCercle cx, cy, abs(100*sinus(angle)), 'blue'
A = new Point 50, 240 B = new Point 600, 20 C = new Point 600, 460 M = new Point dé(640), dé(480) for n in [1..1000] switch dé(3) when 1 M = M.milieu A dessineCercle M.x, M.y, 2, 'red' when 2 M = M.milieu B dessineCercle M.x, M.y, 2, 'blue' else M = M.milieu C dessineCercle M.x, M.y, 2, 'green'
A = new Point 50, 240 B = new Point 600, 20 C = new Point 600, 460 gasket = (a,b,c,N) -> if N < 1 dessinePolygone [[a.x,a.y],[b.x,b.y],[c.x,c.y]], 'black', 'none' else gasket(a, a.milieu(b), a.milieu(c), N-1) gasket(b, b.milieu(c), b.milieu(a), N-1) gasket(c, c.milieu(a), c.milieu(b), N-1) gasket A, B, C, 6
Ceci simule un mouvement brownien :
gauss = () -> Z = -6 Z += alea() for n in [0...12] Z [a,b] = [320,240] for n in [1..1000] [c,d] = [a+gauss(),b+gauss()] dessineSegment a, b, c, d, 'black' [a,b] = [c,d]