lundi 30 décembre 2013

bc : une calculatrice intégrée

Le plus utile, le moins reconnu du mande unix et donc Linux bc:
bc une calculatrice scientifique complète...

bc est une calculatrice basique sous unix. Mais elle n'a de basique que le nom car elle permet d'avoir des possibilités et des fonctionnalités bien plus avancées que la plupart des calculatrices. bc est aux opérations mathématiques ce que awk est à la manipulation de texte.

Petit tour d'horizon

bc possède deux modes d'utilisation, un premier en mode interactif, qui permet de 'lutiliser directement en ligne de commande pour des opérations ponctuelles, un second mode, un mode flot, qui permet d'effectuer des opérations en série (à partir d'un fichier ou d'un script).

mode interactif

Le mode interactif est simplement appelé par la commande bc. Le programme attend ensuite les intructions, tout comme le ferait ftp ou telnet, et s'arrête avec la commande quit. Lançons donc bc :
# bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
puis demandons-lui d'effectuer quelques opérations qu'il suffit de valider par la touche entrée du clavier :
3+5
8
./2
4
./3
1

Remarque

Le point "." permet de rappeler la valeur courante. Dans notre exemple, le point rappelle 8 puis 4.
Nous remarquons que 4/3 renvoie uniquement la partie entière. Pour modifier la précision, il suffit d'utiliser scale :
scale=50
4/3
1.3333333333333333333333333333333333333333333333333
On peut aussi modifier le format de sortie avec obase :
obase=16
85+3
58
On peut aussi modifier le format d'entrée avec ibase :
ibase=2
111011101+110101010
387
Nous avons en entrée une opération en base 2 (binaire) et le résultat est affiché en hexadécimal (base 16).
Et ainsi de suite...

mode flot

Pour effectuer la même chose en mode flot, il suffit de rediriger les opérations d'une entrée vers bc :
# echo 'scale=50; ibase=10;obase=16; 85+49' | bc
86
Ou bien mettre les opérations dans un fichier :
3+5
./2
./3
scale=50
4/3
obase=16
85+3
ibase=2
111011101+110101010
...
en veillant à ce que chaque ligne se termine par un retour chariot et interpréter ces opérations avec bc de la façon suivante :
# cat monfichier.bc | bc
8
4
1
1.33333333333333333333333333333333333333333333333333
58
387
ou encore :
# bc < monfichier.bc
8
4
1
1.33333333333333333333333333333333333333333333333333
58
387
Nous retrouvons bien nos résultats.
Il peut arriver d'avoir à effectuer des opérations sur le contenu d'un fichier. Par exemple, de faire la somme d'une colonne. S'il est possible et aisé de le faire avec awk, bc permet tout aussi bien de le faire. Mais awk peut s'avérer vite moins efficace si les opérations deviennent complexes.
Avec bc, par exemple, une somme de colonne se fera de la façon suivante :
# ls -l | awk 'NR>1 {print ".+" $5}' | bc | tail -1
permet, par exemple de calculer la somme de l'espace occupé par les fichiers du répertoire courant. Ici, c'est une commande ls mais cela peut tout aussi bien être une redirection de fichier, etc.

Fonctions avancées

Si bc ne savait faire que cela, il n'aurait pas beaucoup d'intérêt. Cependant, tout comme awk, bc sait interpréter un langage qui permet de réaliser des fonctions bien plus avancées.

Fonctions avancées en mathématiques

L'option l permet à bc de disposer des opérations mathématiques suivantes :
  • s(x) : sin x
  • c(x) : cos x
  • e(x) : exp x
  • l(x) : ln x
  • a(x) : atn x
  • j(n,x) : bessel
Par exemple :
# echo 'scale=50; l(25)' | bc -l
3.21887582486820074920151866645237527905120270853703

Définir ses propres fonctions

Grâce à un langage associé, bc permet également de définir d'autres fonctions inexistantes. Par exemple :
/* Une fonction pour retourner le log n de x*/
define log(n,x) {
scale=50
y = l(x) / l(n)
return (y)
}
Cette fonction permet de calculer le logarithme en base n de la valeur x.
Cette fonction est créée dans un fichier. Par exemple, fnc.bc. Pour utiliser cette fonction, il suffit alors de l'employer comme suit :
# echo 'log(10,25)' | bc -l fnc.bc
1.39794000867203760957252221055101394646362023707578
Nous avons calculé ainsi le logarithme en base 10 de la valeur 25.
De la même façon, ce langage gère les boucles (if(cond)..., while(cond)... et for(init;cond;inc)...) , les condition (if(cond)..., else ...), etc. Pour plus de détails, reportez-vous au manuel de la commande.
Un problème peut subsister dans cet usage. La notation impose d'utiliser bc -l fnc.bc pour choisir quelle bibliothèque de fonctions personnelles employer. Cela sera plus simple si l'on n'avait pas à utiliser autant de paramètres. Pour cela, modifions notre fichier de définitions et ajouter sur la première ligne :
#!/usr/bin/bc -l
De plus, transformons ce fichier en exécutable en lui donnant les droits d'exécution.
Nous pouvons ainsi utiliser directement la bibliothèque en exécutant ce fichier, soit de manière directe :
# fnc.bc
log(10,25)
1.39794000867203760957252221055101394646362023707578
soit de manière indirecte :
# echo 'log(10,25)' | fnc.bc
1.39794000867203760957252221055101394646362023707578