IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Linux Discussion :

Bash et arithmétique flottante


Sujet :

Linux

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 4
    Par défaut Bash et arithmétique flottante
    Bonjour,

    je viens tout juste de me mettre au bash pour éditer un script bien précis.
    Dans ce script je vais avoir besoin d'initialiser un flottant et l'incrémenter d'un flottant.
    Mais je ne comprends pas bien la "mécanique" de ce langage.
    Par exemple le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    a=0
    b=0.25
    echo "($a+$b)" | bc
    m'affiche le résultat que je désire: 0.25.

    Cependant je ne souhaite pas afficher ce résultat, mais le désigner comme nouvelle valeur de la variable a.

    J'ai essayé des choses du genre (avec ou sans double quote, histoire de se rapprocher au mieux de l'exemple précédent):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    a=0
    b=0.25
    a=$(($a+$b)) | bc
    echo $a
    Selon les tests, ou bien ça m'affiche 0, ou bien j'ai une erreur du type
    0+0.25: erreur de syntaxe : opérateur arithmétique non valable (error token is ".25")
    Merci pour votre aide.

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 860
    Billets dans le blog
    1
    Par défaut
    Salut

    Tu viens de commencer le shell. Tu peux télécharger mon tuto shell ici

    Il faut bien comprendre que le shell est un langage extrêmement limité. Jusqu'à peu de temps, il n'utilisait que des variables de type string et ne connaissait même pas les tableaux. Il n'est pas vraiment fait pour programmer des applis mais plutôt pour automatiser des tâches d'administration.

    Donc quand tu écris
    a=0.7
    b=0.25
    Tu ne fais qu'écrire des chaines dans ces variables que tous les shells ne savent pas forcément additionner (le bash peut le faire mais on va admettre qu'on parle dans un cas général)

    Et donc si tu veux faire un calcul sur ces valeurs, t'es obligé d'envoyer ton calcul dans un programme qui saura l'effectuer. Il y en a qq uns mais on va utiliser bc avec l'option "-l" pour indiquer à bc de travailler en virgules flottantes (sinon il fait ses calculs en int)
    Et donc tu écris "echo $a + $b |bc -l" ce qui signifie "j'envoie la chaine 0.7 + 0.25 au programme bc" qui saura faire le calcul et qui l'affichera à l'écran.

    Maintenant tu veux récupérer le résultat dans une autre variable, tu utilises alors le mécanisme de récupération qui permet de récupérer dans le script ce que la commande affiche à l'écran et qui se symbolise par des backquotes `...`
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    result=`echo "$a + $b" |bc -l`
    echo "Le résultat est: $result"

    Ce mécanisme de backquotes peut être remplacé, en bash, par l'écriture $(...) qui est plus lisible
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    result=$(echo "$a + $b" |bc -l)
    echo "Le résultat est: $result"

    Les shells plus évolués (comme le bash) peuvent faire eux-mêmes les calculs. Il suffit d'entourer ledit calcul par $(()). Ainsi, plus la peine de passer par bc.
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    result=$((2 + 2))
    echo "Le résultat est: $result"
    Toutefois, ce calcul simpliste n'accepte que des entiers. Rappelons que le shell n'est pas destiné à faire des traitements mathématiques. Pour ça, il y a d'autres langages tout aussi sympa que le shell mais plus orientés scientifique. Par exemple Python
    moi@debian:~$ python
    Python 2.5.2 (r252:60911, Jan 4 2009, 17:40:26)
    [GCC 4.3.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> a=0.5
    >>> b=0.25
    >>> a+b
    0.75
    >>> <ctrl-d> (là faut le taper et non l'écrire ce qui permet de quitter l'interpréteur)
    moi@debian:~$
    Python est un très intéressant langage de script qui est cependant fortement typé et qui connait aussi l'objet. Il est aussi facile d'écrire un script Python qu'un script shell. Suffit juste de faire commencer son script par "#!/usr/bin/env python" au lieu de "#!/bin/sh" et nommer son fichier ".py" au lieu de ".sh"

    Qq exemples de la souplesse de ce langage
    moi@debian:~$ python
    Python 2.5.2 (r252:60911, Jan 4 2009, 17:40:26)
    [GCC 4.3.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> print "hello" * 3
    hellohellohello
    >>> a=range(10)
    >>> a
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> b=[x * x for x in a]
    >>> b
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> c=[x for x in a if (x%2) == 0]
    >>> c
    [0, 2, 4, 6, 8]
    >>> d=[x * x for x in a if (x%2) != 0] * 2
    >>> d
    [1, 9, 25, 49, 81, 1, 9, 25, 49, 81]
    >>> <ctrl-d>
    moi@debian:~$
    Pour apprendre ce langage, télécharger l'excellent tuto de Swinnen (taper "swinnen python" dans n'importe quel moteur de recherche). Cependant Python n'est pas fait pour automatiser des tâches d'admin (même s'il a accès par ses librairies à pas mal d'outils systèmes)

    Concernant les calculs, on peut arriver au problème connu de la précision décimale. La conversion d'un décimal en binaire n'est pas forcément toujours parfaite. Exemple: ce calcul ne donnera pas le résultat exact
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    echo "1 / 3 * 3" |bc -l

    Ce problème peut avoir ou pas une certaine importance selon la criticité de l'outil attendu. Si on doit par exemple gérer un compte bancaire, ce serait bien qu'il n'y ait pas d'arrondi à chaque addition/soustraction. Ce n'est pas lié à un défaut du langage mais à la façon de coder en binaire et donc tous les langages y sont soumis (même Python)
    moi@debian:~$ python
    Python 2.5.2 (r252:60911, Jan 4 2009, 17:40:26)
    [GCC 4.3.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 0.3
    0.29999999999999999
    >>> 0.49
    0.48999999999999999
    >>> 0.49*2
    0.97999999999999998
    >>> <ctrl-d>
    moi@debian:~$
    Toutefois, Python possède une super librairie qui s'appelle "decimal" et qui a pour but d'offrir des calculs en exacte précision. Les nombres y sont codés digit par digit et les opérations sont exécutées comme on le fait à la main. Chaque digit est opéré avec chaque autre avec gestion de la retenue, etc. Moins rapide qu'en binaire mais garanti exact
    moi@debian:~$ python
    Python 2.5.2 (r252:60911, Jan 4 2009, 17:40:26)
    [GCC 4.3.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import decimal
    >>> decimal.Decimal("0.49") * 2
    Decimal("0.98")
    >>> a=decimal.Decimal("0.49")
    >>> print a
    0.49
    >>> print a * 2
    0.98
    >>> <ctrl-d>
    moi@debian:~$
    Donc voilà. A toi de voir...

    PS: Python a été porté aussi sous Windows. Faut juste télécharger et installer l'interpréteur et ensuite les scripts Python écrits sous Linux fonctionneront aussi sous Windows.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 685
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    a=0
    b=0.25
    a=$(bc <<<"$a+$b")
    printf '%.2f\n' ${a/./,}
    Il y a deux soucis :
    1/ bc retourne un nombre qui ne commence pas par 0 (je ne sais pas s'il existe une solution)
    2/ ayant des locales en français, printf ne reconnaît pas les nombres décimaux à la mode anglo-saxonne.
    Donc, $a vaut en fait .25, mais je substitue, momentanément, le point par une virgule.
    Ou alors, il faut modifier la valeur de LC_NUMERIC :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    LC_NUMERIC=C
    a=0
    b=0.25
    a=$(bc <<<"$a+$b")
    printf '%.2f\n' $a
    reste que si le résultat est un entier, printf l'affichera tout de même avec une virgule
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 860
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    a=0
    b=0.25
    a=$(bc <<<"$a+$b")
    printf '%.2f\n' ${a/./,}
    Il y a deux soucis :
    1/ bc retourne un nombre qui ne commence pas par 0 (je ne sais pas s'il existe une solution)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    a=0
    b=0.25
    a=$(echo "0.5" |bc |sed -e "s/^\./0./" -e "s/\./,/")
    printf '%.2f\n' $a
    Citation Envoyé par N_BaH Voir le message
    reste que si le résultat est un entier, printf l'affichera tout de même avec une virgule
    echo $a
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 685
    Par défaut
    Citation Envoyé par Sve@r
    echo $a
    mais alors on n'a plus le zéro pour le nombre décimaux 0 < n < 1
    ...
    ?
    ou alors il faut tester la présence d'un "séparateur décimal"

    Edit: ah! ok, j'avais pas vu le sed.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 4
    Par défaut
    Merci bien à vous deux pour ces explications, c'est bien plus clair. Et merci aussi pour le tuto, il est bien plus complet que ce que j'ai réussi à obtenir via google (j'aurais peut-être du taper shell au lieu de bash).

    C'est pour faire un script où essentiellement je manipule des fichiers, j'ai la contrainte de le faire en shell pour une question de portabilité. Néanmoins, faisant pas mal de maths, cette incursion en python m'intéresse beaucoup, je vais chercher le tutoriel dont tu me parles Sve@r.

    Bonne soirée.

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 860
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par lgndslpgs Voir le message
    Néanmoins, faisant pas mal de maths, cette incursion en python m'intéresse beaucoup, je vais chercher le tutoriel dont tu me parles Sve@r.
    Ok, alors bien que la dernière version de Python soit la 3.2, il vaut mieux te concentrer sur Python 2.5. Parce que la version 3 de Python a apporté énormément de modification et qu'elle n'est pas compatible Python 2. Et toutes les librairies diverses et variées (on peut créer du PDF, de l'excel, programmer une IHM, programmer un GPS, etc) n'ont pas encore toutes été portées en Python 3.

    Tu trouveras aussi Python 2.6 et 2.7 (sauf pour Windows où Python s'est arrêté à 2.6) mais là encore, toutes les librairies en environnement windows n'ont pas toutes été portées pour 2.6. Donc moi je suis resté à la 2.5 qui me va pour l'instant très bien...

    Voici le tuto http://python.developpez.com/cours/apprendre-python3/

    Tu pourras aussi rechercher dive into Python qui est lui aussi un tuto extrêmement pointu...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 4
    Par défaut
    Merci Sve@r pour ces compléments, j'ai trouvé la page du dive into Python. Sur Karmic j'ai la version 2.6.4, je vais suivre tes conseils et mettre la 2.5.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. arithmétique et bash ?
    Par AkiyamaS dans le forum Shell et commandes GNU
    Réponses: 3
    Dernier message: 24/05/2012, 19h09
  2. Opérations arithmétiques en bash
    Par Tanakaa dans le forum Shell et commandes GNU
    Réponses: 7
    Dernier message: 15/10/2009, 18h46
  3. Unité arithmétique et flottante
    Par John Fullspeed dans le forum x86 32-bits / 64-bits
    Réponses: 5
    Dernier message: 21/10/2004, 17h50
  4. Créer une fenêtre flottante qui ne peut avoir le focus
    Par BestofMac dans le forum Composants VCL
    Réponses: 4
    Dernier message: 17/07/2002, 10h46
  5. [Kylix] Probleme de nombre flottant!!
    Par yopziggy dans le forum EDI
    Réponses: 5
    Dernier message: 02/05/2002, 10h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo