Mathématiques avec Python et Ruby/Nombres entiers en Ruby

Un livre de Wikilivres.

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[modifier | modifier le wikicode]

Avec une chaîne de caractères[modifier | modifier le wikicode]

Si 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[modifier | modifier le wikicode]

La 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[modifier | modifier le wikicode]

Pour 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[modifier | modifier le wikicode]

Pour 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[modifier | modifier le wikicode]

Addition, soustraction et multiplication[modifier | modifier le wikicode]

Dans 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[modifier | modifier le wikicode]

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[modifier | modifier le wikicode]

le 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[modifier | modifier le wikicode]

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 %:

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é[modifier | modifier le wikicode]

En 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[modifier | modifier le wikicode]

L'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:

  1. Si l'exposant est négatif, le résultat est une fraction;
  2. Si l'exposant est réel, le résultat est réel aussi.

Priorités opératoires[modifier | modifier le wikicode]

En Ruby comme en algèbre, on effectue dans l'ordre

  1. Les parenthèses
  2. Les fonctions (comme l'élévation à une puissance)
  3. Les multiplications et divisions
  4. 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[modifier | modifier le wikicode]

Itérateur[modifier | modifier le wikicode]

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[modifier | modifier le wikicode]

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

oui=10
oui.times do puts("Yes!") end

Avec un indice[modifier | modifier le wikicode]

Pour 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[modifier | modifier le wikicode]

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

à nombre prédéterminé d'exécutions[modifier | modifier le wikicode]

Pour 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[modifier | modifier le wikicode]

La 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)