Objectifs
- Effectuer des calculs sur des nombres entiers avec la syntaxe
$((...)). - Comprendre les limites de l’arithmétique native de Bash (pas de flottants).
- Utiliser l’outil externe
bcpour réaliser des calculs avec des nombres à virgule flottante. - Incrémenter des compteurs dans des scripts.
Explications détaillées
Notions clés
L’Arithmétique sur les Entiers : $((...))
Bash dispose d’un mécanisme intégré pour gérer les calculs sur les nombres entiers uniquement. La syntaxe la plus moderne et la plus lisible est l’expansion arithmétique.
result=$(( expression ))
Le shell évalue ce qui se trouve entre les doubles parenthèses et remplace toute l’expression par le résultat numérique.
Point important : À l’intérieur de ((...)), vous n’avez pas besoin de mettre le signe $ devant vos variables.
Les limites : pas de nombres à virgule flottante
Bash ne comprend nativement que les entiers. Toute division sera une division entière (qui tronque le résultat).
echo $(( 5 / 2 ))
2
bc : La calculatrice pour la ligne de commande
Pour effectuer des calculs avec des nombres à virgule flottante, il faut utiliser un outil externe. Le plus courant est bc (Basic Calculator).
On lui envoie une chaîne de caractères contenant le calcul via un pipe |.
scale=N: Définit le nombre de décimales pour le résultat.-l: Charge la bibliothèque mathématique standard (poursin,cos,sqrt, etc.).
Syntaxe / Usages
# Calculs entiers simples
result=$(( 10 + 5 * 2 )) # Respecte la priorité des opérations
echo $result # -> 20
# Incrémenter une variable
count=0
count=$((count + 1))
# Ou plus court avec l'opérateur ++
((count++))
echo $count # -> 2
# Division entière
echo $(( 10 / 3 )) # -> 3
# Reste (modulo)
echo $(( 10 % 3 )) # -> 1
# Calcul flottant avec bc
echo "scale=4; 10 / 3" | bc
# -> 3.3333
# Calcul plus complexe avec bc et la librairie mathématique
echo "scale=10; s(1)" | bc -l # sinus de 1 radian
Exemples
# 1. Un simple compteur dans une boucle
for i in {1..5}; do
echo "Tour de boucle numéro $((i))"
done
# 2. Calculer un pourcentage (astuce avec des entiers)
# On multiplie par 100 d'abord pour préserver la précision avant la division
total=150
partiel=45
pourcentage=$(( (100 * partiel) / total ))
echo "$partiel représente $pourcentage% de $total"
# 3. Calculer l'aire d'un cercle avec bc
RAYON=5.5
# Notez l'utilisation de guillemets pour passer l'expression à echo
AIRE=$(echo "scale=2; 3.14159 * $RAYON * $RAYON" | bc)
echo "L'aire d'un cercle de rayon $RAYON est d'environ $AIRE"
Bonnes pratiques
- Toujours utiliser
$((...))pour les calculs sur les entiers. C’est plus lisible et plus sûr que les anciennes syntaxes commeexpr. - Quand vous avez besoin de flottants, utilisez
bc. C’est l’outil standard et portable pour cela.awkest une autre alternative puissante. - Dans
$((...)), les variables peuvent être utilisées sans le$, ce qui allège la syntaxe :a=5; echo $((a + 3)).
Pièges courants
- Essayer de faire des calculs flottants en Bash natif :
echo $((5.5 + 1))résultera en une erreur de syntaxe. - Oublier
scaleavecbc: Si vous faitesecho "5 / 2" | bc, le résultat sera2, car par défaut,scaleest à0. Il faut toujours le définir pour les divisions. - La sortie de
bcpeut avoir des zéros non significatifs :echo "scale=4; 10/2" | bcdonnera5.0000. Il faut parfois retraiter la chaîne si on veut un affichage plus propre.
Exercices
-
Calculatrice simple :
- Écrivez un script qui prend deux nombres entiers comme arguments et affiche leur somme, leur différence, leur produit et leur quotient entier.
- Exemple :
./calcul.sh 10 3
-
Conversion de température :
- Écrivez un script qui prend une température en Celsius en argument et la convertit en Fahrenheit en utilisant
bc. - Formule :
F = (C * 9/5) + 32. Le résultat doit avoir une décimale. - Exemple :
./convert.sh 20doit afficher environ68.0.
- Écrivez un script qui prend une température en Celsius en argument et la convertit en Fahrenheit en utilisant
-
Somme des N premiers entiers :
- Écrivez un script qui utilise une boucle
foret une expansion arithmétique pour calculer la somme des entiers de 1 à 100.
- Écrivez un script qui utilise une boucle