如何让bc(1)打印前导零?

时间:2011-12-06 15:16:01

标签: bash unix bc

我在Makefile中执行以下操作:

echo "0.1 + 0.1" | bc

(在真实文件中,数字当然是动态的)

它会打印.2,但我希望它能打印0.2

我想这样做而不诉诸sed,但我似乎无法找到如何让bc打印零。或bc无法做到这一点?

12 个答案:

答案 0 :(得分:38)

您也可以使用awk格式化:

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

或者用awk本身做数学运算:

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

答案 1 :(得分:33)

这可能对您有用:

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

答案 2 :(得分:23)

快速查看the source(参见bc_out_num(),第1461行)后,如果整数部分为{,我看不到明显的方法使得前导0得到打印{1}}。除非我遗漏了某些内容,否则此行为不依赖于可以使用命令行标志更改的参数。

简短回答:不,我认为没有办法按照您想要的方式制作0打印数字。

如果您仍想使用bc,我认为使用sed时没有任何问题。以下看起来并不可怕,恕我直言:

bc

如果你真的想避免[me@home]$ echo "0.1 + 0.1" | bc | sed 's/^\./0./' 0.2 ,那么eljunior'schoroba's建议都非常简洁,但它们需要依赖于值的调整以避免尾随零。这对您来说可能是也可能不是问题。

答案 3 :(得分:9)

我在文档中找不到任何有关输出格式的内容。而不是sed,你也可以达到printf:

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

答案 4 :(得分:3)

这个也将处理负数:

echo "0.1 - 0.3" | bc | sed -r 's/^(-?)\./\10./'

答案 5 :(得分:3)

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

这是纯粹的bc。它通过比较length的结果与表达式的scale来检测前导零。它适用于正数和负数。

答案 6 :(得分:2)

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

这适用于结果为:

的所有情况
  • &#34; - 123&#34;
  • &#34; 0.123&#34;
  • &#34; -1.23&#34;
  • &#34; 1.23&#34;

说明:

  1. 对于仅以-.开头的所有内容,请将-.替换为-0.

  2. 对于仅以.开头的所有内容,请将.替换为0.

答案 7 :(得分:2)

对于正数,它可能就像打印(字符串)零一样简单:

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

如果数字大于(或等于)1,则避免零:

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

如果数字可能为负,则会更复杂一些:

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

您可以定义一个函数并将其添加到库中:

$ 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

答案 8 :(得分:1)

这只使用bc,并使用负数:

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

尝试:

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

答案 9 :(得分:1)

可能bc并不是最好的&#34;替补计算器&#34;适合现代。其他语言将为您提供更多控制。下面是一些工作示例,它们在范围(-1.0 .. + 1.0)中打印值为前导零。这些示例使用bcAWKPython 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)")
   }

请注意,如果重要的话,Python版本的速度要慢10倍。

答案 10 :(得分:0)

建立在potongs answer上,

对于小数结果:

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

请注意,否定结果将无法正确显示。水瓶座力量有solution

答案 11 :(得分:0)

另一种简单的方法,类似于本主题 here 中的一个帖子:

echo 'x=0.1+0.1; print "0",x,"\n"' | bc

打印变量列表,包括前导 0 和换行符。