web-dev-qa-db-fra.com

Comment obtenir que bc (1) imprime le zéro non significatif?

Je fais quelque chose comme ce qui suit dans un Makefile:

echo "0.1 + 0.1" | bc

(dans le vrai fichier les nombres sont dynamiques, bien sûr)

Il imprime .2 mais je veux qu’il imprime 0.2.

Je voudrais faire ceci sans recourir à sed mais je n'arrive pas à trouver comment obtenir bc pour imprimer le zéro. Ou bc n'est-il simplement pas capable de faire cela?

56
rwos

Vous pouvez également recourir à awk pour formater:

 echo "0.1 + 0.1" | bc | awk '{printf "%f", $0}'

ou avec awk elle-même faisant le calcul:

 echo "0.1 0.1" | awk '{printf "%f", $1 + $2}'
38
elias

Cela pourrait fonctionner pour vous:

echo "x=0.1 + 0.1; if(x<1) print 0; x" | bc
33
potong

Après un coup d’œil rapide sur la source (voir bc_out_num(), ligne 1461), je ne vois pas de moyen évident d’imprimer le 0 qui précède soit imprimé si la partie entière est 0. À moins que quelque chose ne m'ait échappé, ce comportement ne dépend pas d'un paramètre qui peut être modifié à l'aide d'un indicateur de ligne de commande.

Réponse courte: non, je ne pense pas qu'il soit possible de faire imprimer des numéros bc comme vous le souhaitez.

Je ne vois aucun inconvénient à utiliser sed si vous souhaitez toujours utiliser bc. Ce qui suit ne semble pas si affreux, à mon humble avis:

[me@home]$ echo "0.1 + 0.1" | bc | sed 's/^\./0./'
0.2

Si vous voulez vraiment éviter sed, les deux suggestions de eljunior et choroba sont plutôt soignées, mais elles nécessitent un ajustement dépendant de la valeur pour éviter les zéros. Cela peut ou peut ne pas être un problème pour vous.

23
Shawn Chin

Je ne trouve rien sur le format de sortie dans la documentation. Au lieu de sed, vous pouvez également accéder à printf:

printf '%3.1f\n' $(bc<<<0.1+0.1)
9
choroba

Celui-ci traitera également les nombres négatifs:

echo "0.1 - 0.3" | bc | sed -r 's/^(-?)\./\10./'
3
user3420895
$ bc -l <<< 'x=-1/2; if (length (x) == scale (x) && x != 0) { if (x < 0) print "-",0,-x else print 0,x } else print x'

Celui-ci est pur bc. Il détecte le zéro initial en comparant le résultat de length avec scale de l'expression. Cela fonctionne sur les nombres positifs et négatifs.

3
gomibako

Pour les nombres positifs, cela peut être aussi simple que d’imprimer (une chaîne) zéro:

$ echo '"0";0.1+0.1' | bc
0.2

éviter le zéro si le nombre est plus grand (ou égal) à 1:

$ echo 'x=0.1+0.1;  if(x<1){"0"};  x' | bc
0.2

Cela devient un peu plus complexe si le nombre peut être négatif:

echo 'x= 0.3 - 0.5 ; s=1;if(x<0){s=-1};x*=s;if(s<0){"-"};if(x<1) {"0"};x' | bc
-0.2

Vous pouvez définir une fonction et l'ajouter à une bibliothèque:

$ echo 'define leadzero(x){auto s;
        s=1;if(x<0){s=-1};x*=s;if(s<0){"-"};if(x<1){"0"};
        return(x)};
        leadzero(2.1-12.4)' | bc
-10.3

$ echo 'define leadzero(x){auto s;
        s=1;if(x<0){s=-1};x*=s;if(s<0){"-"};if(x<1){"0"};
        return(x)};
        leadzero(0.1-0.4)' | bc
-0.3
2
Isaac

echo "$a / $b" | bc -l | sed -e 's/^-\./-0./' -e 's/^\./0./'

Cela devrait fonctionner dans tous les cas où les résultats sont:

  • "-.123"
  • ".123"
  • "-1.23"
  • "1.23"

Explication:

  1. Pour tout ce qui ne commence que par -., remplacez -. par -0.

  2. Pour tout ce qui ne commence que par ., remplacez . par 0.

2
cafemike

bc n'est probablement pas le meilleur "calculateur de banc" du monde moderne. D'autres langues vous donneront plus de contrôle. Voici des exemples de travail qui affichent des valeurs dans la plage (-1.0 .. + 1.0) avec un zéro non significatif. Ces exemples utilisent bc , AWK et Python 3 .

#!/bin/bash

echo "using bc"
time for (( i=-2; i<=+2; i++ ))
   {
   echo $(bc<<<"scale=1; x=$i/2; if (x==0||x<=-1||x>=1) { print x } else { if (x<0) { print \"-0\";-x } else { print \"0\";x } } ")
   }
echo

echo "using awk"
time for (( i=-2; i<=+2; i++ ))
   {
   echo $(echo|awk "{printf \"%.1f\",$i/2}")
   }  
echo

echo "using Python"
time for (( i=-2; i<=+2; i++ ))
   {
   echo $(python3<<<"print($i/2)")
   }

Notez que la version Python est environ 10 fois plus lente, si cela compte.

1
nobar

cela utilise uniquement bc et fonctionne avec des nombres négatifs:

bc <<< "x=-.1; if(x==0) print \"0.0\" else if(x>0 && x<1) print 0,x else if(x>-1 && x<0) print \"-0\",-x else print x";

essayez-le avec:

for y in "0" "0.1" "-0.1" "1.1" "-1.1"; do
  bc <<< "x=$y; if(x==0) print \"0.0\" else if(x>0 && x<1) print 0,x else if(x>-1 && x<0) print \"-0\",-x else print x";
  echo;
done
1
Aquarius Power

Construire sur des potongs répondre

Pour des résultats fractionnaires:

echo "x=0.1 + 0.1; if(x<1 && x > 0) print 0; x" | bc -l

Notez que les résultats négatifs ne seront pas affichés correctement. Aquarius Power a une solution pour cela. 

0
Oliver Grant