72

我在 Makefile 中执行以下操作:

echo "0.1 + 0.1" | bc

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

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

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

4

12 回答 12

46

你也可以使用 awk 来格式化:

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

或者用 awk 自己做数学:

 echo "0.1 0.1" | awk '{printf "%f", $1 + $2}'
于 2011-12-06T15:38:33.760 回答
38

这可能对您有用:

echo "x=0.1 + 0.1; if(x<1) print 0; x" | bc
于 2011-12-06T17:50:47.067 回答
30

在快速查看源代码后(请参阅bc_out_num()第 1461 行),0如果整数部分是0. 除非我错过了什么,否则此行为不依赖于可以使用命令行标志更改的参数。

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

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

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

如果你真的想避免sedeljuniorchoroba 的建议都非常简洁,但它们需要依赖于值的调整以避免尾随零。这对你来说可能是也可能不是问题。

于 2011-12-06T16:19:11.990 回答
12

我在文档中找不到任何关于输出格式的信息。除了 sed,您还可以使用 printf:

printf '%3.1f\n' $(bc<<<0.1+0.1)
于 2011-12-06T15:23:52.043 回答
4

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

这应该适用于结果为:

  • “-.123”
  • “.123”
  • “-1.23”
  • “1.23”

解释:

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

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

于 2017-11-03T04:39:54.513 回答
3

这也将处理负数:

echo "0.1 - 0.3" | bc | sed -r 's/^(-?)\./\10./'
于 2014-03-14T17:11:02.303 回答
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'

这个是纯的bclength它通过将表达式的结果与表达式的结果进行比较来检测前导零scale。它适用于正数和负数。

于 2015-07-30T23:32:30.453 回答
3

建立在potongs答案的基础上,

对于分数结果:

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

请注意,否定结果将无法正确显示。Aquarius Power 有一个解决方案

于 2017-03-14T12:59:47.537 回答
3

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

$ 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
于 2018-05-08T08:41:57.903 回答
2

可能,bc它并不是现代最好的“台式计算器”。其他语言会给你更多的控制。以下是打印范围 (-1.0..+1.0) 中的值并带有前导零的工作示例。这些示例使用bc,AWKPython 3, 以及Here String语法。

#!/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 倍(对于大多数用途来说仍然非常快)。


sh用or做任何重要的数学运算bc都是徒劳的。现在有更好的台式计算器。例如,您可以使用Here Documents在 Bash 脚本中嵌入和执行 Python 子例程。

function mathformatdemo {
python3<<SCRIPT
import sys
from math import *
x=${1} ## capture the parameter from the shell
if -1<=x<=+1:
    #print("debug: "+str(x),file=sys.stderr)
    y=2*asin(x)
    print("2*asin({:2.0f})={:+6.2f}".format(x,y))
else: print("domain err")
SCRIPT
}

echo "using Python via Here-doc"
time for (( i=-2; i<=+2; i++ ))
   {
   echo $(mathformatdemo $i)
   }

输出:

using Python via Here-doc
domain err
2*asin(-1)= -3.14
2*asin( 0)= +0.00
2*asin( 1)= +3.14
domain err
于 2015-04-20T22:05:20.083 回答
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
于 2013-06-09T06:25:45.770 回答
0

另一种简单的方法,类似于此处此线程中的帖子之一:

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

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

于 2021-06-18T19:02:59.347 回答