J'essaye de comparer deux nombres à virgule flottante dans un script bash. Je dois des variables, par exemple
let num1=3.17648e-22
let num2=1.5
Maintenant, je veux juste faire une simple comparaison de ces deux nombres:
st=`echo "$num1 < $num2" | bc`
if [ $st -eq 1]; then
echo -e "$num1 < $num2"
else
echo -e "$num1 >= $num2"
fi
Malheureusement, j'ai quelques problèmes avec le bon traitement du num1 qui peut être du "e-format". :(
Toute aide, conseils sont les bienvenus!
Réponses:
Plus commodément
Cela peut être fait plus facilement en utilisant le contexte numérique de Bash:
Explication
Le fait de passer par la commande de base de la calculatrice
bc
renvoie 1 ou 0.L'option
-l
équivaut à--mathlib
; il charge la bibliothèque mathématique standard.Mettre l'expression entière entre doubles parenthèses
(( ))
traduira ces valeurs respectivement en vrai ou en faux.Veuillez vous assurer que le
bc
package de base de la calculatrice est installé.Cela fonctionne également pour les flotteurs au format scientifique, à condition qu'une lettre majuscule
E
soit utilisée, par exemplenum1=3.44E6
la source
bc
package de calculatrice est installé.0: not found
avec la déclarationif (( $(echo "$TOP_PROCESS_PERCENTAGE > $THRESHOLD" | bc -l) )); then
.bc
placer le soit dans les backticks ou$()
puis dans(( ))
... c'est(( $(bc -l<<<"$a>$b") ))
-à- dire et non(( bc -l<<<"$a>$b" ))
.E
et toutes les erreurs de syntaxe auront disparu.bash ne gère que les nombres entiers, mais vous pouvez utiliser la
bc
commande comme suit:Notez que le signe de l'exposant doit être en majuscule
la source
bc
outil et c'est ce que je recommanderais à tout programmeur BASH. BASH est un langage sans type. Oui, il peut faire de l'arithmétique entière, mais pour la virgule flottante, vous devez utiliser un outil externe. BC est le meilleur parce que c'est pour cela qu'il est fait.Il est préférable de l'utiliser
awk
pour les mathématiques non entières. Vous pouvez utiliser cette fonction utilitaire bash:Et appelez-le comme:
la source
awk
etbc
dans les scripts shell est une pratique standard depuis l'Antiquité, je dirais que certaines fonctionnalités n'ont jamais été ajoutées aux shells car elles sont disponibles dans awk, bc et d'autres outils Unix. Pas besoin de pureté dans les scripts shell.exit
pour qu'Awk communique le résultat au shell d'une manière correcte et lisible par machine.if awk -v n1="123.456" -v n2="3.14159e17" 'BEGIN { exit (n1 <= n2) }' /dev/null; then echo bigger; else echo not; fi
... mais notez comment la condition est inversée (le statut de sortie 0 signifie que le shell réussit).python
. Vous avezperl
installé par défaut sur de nombreux systèmes Linux / Unix .. mêmephp
aussiawk
solution est plus robuste dans mon cas que celle avecbc
qui renvoie des résultats erronés pour une raison que je n'ai pas obtenue.Solution pure bash pour comparer des flottants sans notation exponentielle, zéros de début ou de fin:
L'ordre des opérateurs logiques est important . Les parties entières sont comparées sous forme de nombres et les parties fractionnaires sont intentionnellement comparées sous forme de chaînes. Les variables sont divisées en parties entières et fractionnaires à l'aide de cette méthode .
Ne comparera pas les flottants avec des entiers (sans point).
la source
vous pouvez utiliser awk combiné avec une condition bash if, awk affichera 1 ou 0 et ceux-ci seront interprétés par la clause if avec vrai ou faux .
la source
if (( $(echo $d1 $d2 | awk '{if ($1 > $2) print 1;}') )); then echo "yes"; else echo "no"; fi
méfiez-vous lorsque vous comparez des nombres qui sont des versions de package, comme vérifier si grep 2.20 est supérieur à la version 2.6:
J'ai résolu ce problème avec une telle fonction shell / awk:
la source
dpkg --compare-versions
est souvent utile. Il a toute la logique pour comparer les versions de paquet Debian intégrées, qui sont plus complexes que justex.y
.Bien sûr, si vous n'avez pas vraiment besoin d'arithmétique à virgule flottante, juste de l'arithmétique sur, par exemple, des valeurs en dollars où il y a toujours exactement deux chiffres décimaux, vous pouvez simplement supprimer le point (multipliant effectivement par 100) et comparer les entiers résultants.
Cela nécessite évidemment que vous soyez sûr que les deux valeurs ont le même nombre de décimales.
la source
J'ai utilisé les réponses d'ici et les ai mises dans une fonction, vous pouvez l'utiliser comme ceci:
Une fois appelé,
echo $result
sera1
dans ce cas, sinon0
.La fonction:
Ou une version avec sortie de débogage:
Enregistrez simplement la fonction dans un
.sh
fichier séparé et incluez-la comme ceci:la source
Je postais ceci en réponse à https://stackoverflow.com/a/56415379/1745001 quand il a été fermé en tant que dup de cette question, alors le voici comme cela s'applique ici aussi:
Pour plus de simplicité et de clarté, utilisez simplement awk pour les calculs car c'est un outil UNIX standard et donc tout aussi susceptible d'être présent que bc et beaucoup plus facile à utiliser syntaxiquement.
Pour cette question:
et pour cette autre question qui a été fermée comme une dupe de celle-ci:
la source
awk
et des outils comme celui-ci (je vous regarde fixementsed
...) devraient être relégués à la poubelle des vieux projets, avec du code que tout le monde a trop peur de toucher puisqu'il a été écrit dans un langage sans lecture.Ou vous êtes le projet relativement rare qui doit donner la priorité à l'optimisation de l'utilisation du processeur par rapport à l'optimisation de la maintenance du code ... auquel cas, continuez.
Sinon, pourquoi ne pas utiliser à la place quelque chose de lisible et explicite, comme
python
? Vos collègues codeurs et votre futur moi vous remercieront. Vous pouvez utiliser enpython
ligne avec bash comme tous les autres.la source
not(...)
place de0 if ... else 1
awk '${print $5}' ptpd_log_file | perl -ne '$_ > 0.000100 && print' > /tmp/outfile
. Peasy facile. Chaque langue a sa place.python -c "import sys; sys.exit(0 if float($num1) < float($num2) else 1)"
est simplementawk "BEGIN{exit ($num1 > $num2 ? 0 : 1)}"
.Ce script peut aider lorsque je vérifie si la
grails
version installée est supérieure au minimum requis. J'espère que ça aide.la source
la source
veuillez vérifier le code édité ci-dessous: -
cela fonctionne bien.
la source
Une solution prenant en charge toutes les notations possibles, y compris la notation scientifique avec des exposants majuscules et minuscules (par exemple,
12.00e4
):la source
Utilisez korn shell, dans bash, vous devrez peut-être comparer la partie décimale séparément
la source
En utilisant bashj ( https://sourceforge.net/projects/bashj/ ), un mutant bash avec support java, il vous suffit d'écrire (et c'est facile à lire):
Bien sûr, l'hybridation bashj bash / java offre bien plus ...
la source
Que dis-tu de ça? = D
la source
exit 0
rapporter la vérité etexit 1
renvoyer faux; alors vous pouvez simplifier au remarquablement élégantif awk 'BEGIN { exit (ARGV[1] >= ARGV[2]) ? 0 : 1 }' "$VAL_TO_CHECK" 1; then
... (plus élégant encore si vous encapsulez le script Awk dans une fonction shell).