ti-enxame.com

Como obtenho bc (1) para imprimir o zero inicial?

Eu faço algo parecido com o seguinte em um Makefile:

echo "0.1 + 0.1" | bc

(no arquivo real os números são dinâmicos, claro)

Ele imprime .2 mas eu quero imprimir 0.2.

Eu gostaria de fazer isso sem recorrer a sed, mas não consigo encontrar como obter bc para imprimir o zero. Ou é bc simplesmente não é capaz de fazer isso?

56
rwos

Você também pode recorrer ao awk para formatar:

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

ou com o próprio awk fazendo as contas:

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

Isso pode funcionar para você:

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

Depois de uma rápida olhada em a fonte (consulte bc_out_num(), linha 1461), não vejo uma maneira óbvia de fazer o 0 inicial ser impresso se a parte inteira for 0. A menos que eu tenha perdido alguma coisa, esse comportamento não depende de um parâmetro que pode ser alterado usando o sinalizador de linha de comando.

Resposta curta: não, eu não acho que há uma maneira de fazer números de impressão bc do jeito que você quiser.

Não vejo nada de errado em usar sed se você ainda quiser usar bc. O seguinte não parece tão medonho, IMHO:

[[email protected]]$ echo "0.1 + 0.1" | bc | sed 's/^\./0./'
0.2

Se você realmente quer evitar sed, ambos eljunior's e choroba's suggestions são bem legais, mas requerem ajustes dependentes de valor para evitar zeros à direita. Isso pode ou não ser um problema para você.

23
Shawn Chin

Não consigo encontrar nada sobre o formato de saída na documentação. Em vez de sed, você também pode acessar printf:

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

Este também irá lidar com números negativos:

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'

Este é puro bc. Ele detecta o zero inicial comparando o resultado do length com o scale da expressão. Trabalha no número positivo e negativo.

3
gomibako

Para números positivos, pode ser tão simples quanto imprimir (uma string) zero:

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

evite o zero se o número for maior (ou igual) a 1:

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

Fica um pouco mais complexo se o número for negativo:

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

Você pode definir uma função e adicioná-la a uma biblioteca:

$ 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./'

Isso deve funcionar para todos os casos em que os resultados são:

  • "-.123"
  • ".123"
  • "-1,23"
  • "1,23"

Explicação:

  1. Para tudo o que começa somente com -., substitua -. por -0.

  2. Para tudo o que começa somente com ., substitua . por 0.

2
cafemike

Provavelmente, bc não é realmente a melhor "calculadora de bancada" para a era moderna. Outras línguas lhe darão mais controle. Aqui estão exemplos de trabalho que imprimem valores no intervalo (-1.0 .. + 1.0) com um zero à esquerda. Esses exemplos usam bc , AWK e 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)")
   }

Observe que a versão do Python é 10x mais lenta, se isso for importante.

1
nobar

isso usa apenas bc e funciona com números negativos:

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";

tente com:

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

Construindo em potongs answer

Para resultados fracionários:

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

Observe que os resultados negativos não serão exibidos corretamente. Aquarius Power tem um solução para isso. 

0
Oliver Grant