Mathématiques avec Python et Ruby/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
modifierAvec une chaîne de caractères
modifierSi on entre le script suivant:
a=7
puts(a)
on a exactement le même effet que si on entre
a="7"
puts(a)
du moins en apparence. Parce que si on essaye d'additionner 2, avec
a=7
puts(a+2)
on a 9, alors qu'avec
a="7"
puts(a+2)
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
a="7"
b=a.to_i
puts(b+2)
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:
t="abracadabrantesque"
n=t.length
puts(n)
Avec un réel
modifierLa méthode to_i permet aussi de convertir un réel en entier. Ce qui est parfois nécessaire parce que pour Ruby, n'est pas un entier:
a=Math.sqrt(100)
puts(a.integer?)
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:
a=Math.sqrt(100).to_i
puts(a.integer?)
affiche bien true.
a=3.9999999
b=a.to_i
puts(b)
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:
a=3.9999999
b=a.floor
puts(b)
Si on veut arrondir au-dessus, on utilise la méthode ceil d'un réel:
a=3.9999999
b=a.ceil
puts(b)
mais là on tombe dans le problème inverse:
a=3.0000001
b=a.ceil
puts(b)
donne aussi 4 !
Pour arrondir au mieux, on utilise la méthode round:
a=3.9999999
b=a.round
puts(b)
Avec un entier
modifierPour avoir le successeur d'un entier, on utilise la méthode succ:
puts(7.succ)
nous apprend que 7+1=8 (on s'en doutait un peu...), alors que
puts(7.pred)
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,
a=-5
puts(-a)
Donne 5, car l'opposé de -5 est 5.
tests sur les entiers
modifierPour savoir si 2 est entier (on ne sait jamais), on peut le vérifier par
puts(2.integer?)
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:
require 'mathn'
a=2**32+1
puts(a.prime?)
nous apprend que 4 294 967 297 n'est pas premier, contrairement à ce qu'avait conjecturé Fermat.
Opérations
modifierAddition, soustraction et multiplication
modifierDans Ruby, les opérations arithmétiques sont notées +, - et * sans grande surprise. Ces opérations peuvent porter sur des entiers négatifs:
a=5
b=-8
puts(a+b)
puts(a-b)
puts(a*b)
Division
modifierPar défaut, la division des entiers est la division euclidienne. Son quotient est donc un entier (et n'est pas le quotient exact)
Quotient
modifierle script suivant:
num=3
den=2
q=num/den
puts(q)
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
puts(3.0/2)
puts(3/2.0)
puts(3.0/2.0)
puts(3.to_f/2)
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
modifierLorsqu'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 %:
a=13
b=8
r=a%b
puts(r)
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é
modifierEn Ruby, l'opération pgcd est infixée. Pour chercher le plus grand entier qui divise à la fois 13572468 et 12345678, on entre
a=13572468
b=12345678
g=a.gcd(b)
puts(g)
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:
require 'prime'
n=2010
puts(n.prime?)
puts(n.prime_division)
Et en bonus, la décomposition en facteurs premiers!
Puissances
modifierL'opérateur d'élévation à la puissance se note avec l'astérisque de la multiplication, mais dédoublée:
a=4
b=2
puts(a**b)
puts(b**a)
pour vérifier que (Exercice: Quelles sont les autres solutions de l'équation ?)
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
modifierEn 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
puts(2+3*5)
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
modifierItérateur
modifierLa 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
modifierPour écrire un message très enthousiaste, on peut écrire
oui=10
oui.times do puts("Yes!") end
Avec un indice
modifierPour additionner les entiers successifs, on peut le faire avec
somme=0
n=10
n.times do |indice| somme+=indice end
puts(somme)
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
n=10
n.times do |indice| puts(indice) end
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:
(1..10).inject {|somme, indice| somme+indice}
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
modifierRuby permet aussi de faire de la programmation impérative avec des boucles:
à nombre prédéterminé d'exécutions
modifierPour additionner les entiers de 1 à 10, on peut aussi faire comme ceci:
somme=0
for indice in 1..10 do
somme+=indice
end
puts(somme)
Cette fois-ci on a bien 55.
à condition de sortie
modifierLa même somme peut aussi être calculée avec cette boucle:
somme,indice=0,0
while indice<=10 do
somme+=indice
indice=indice.succ
end
puts(somme)