let
和 expr
都无法进行浮点运算,但是 bc
和 awk
可以。
范例:求 1 除以 13,保留 3 位有效数字
$ echo "scale=3; 1/13" | bc
.076
$ echo "1 13" | awk '{printf("%0.3f\n",$1/$2)}'
0.077
说明: bc
在进行浮点运算时需指定精度,否则默认为 0,即进行浮点运算时,默认结果只保留整数。而 awk
在控制小数位数时非常灵活,仅仅通过 printf
的格式控制就可以实现。
补充:在用 bc
进行运算时,如果不用 scale
指定精度,而在 bc
后加上 -l
选项,也可以进行浮点运算,只不过这时的默认精度是 20 位。例如:
$ echo 1/13100 | bc -l
.00007633587786259541
范例:余弦值转角度
用 bc -l
计算,可以获得高精度:
$ export cos=0.996293; echo "scale=100; a(sqrt(1-$cos^2)/$cos)*180/(a(1)*4)" | bc -l
4.934954755411383632719834036931840605159706398655243875372764917732
5495504159766011527078286004072131
当然也可以用 awk
来计算:
$ echo 0.996293 | awk '{ printf("%s\n", atan2(sqrt(1-$1^2),$1)*180/3.1415926535);}'
4.93495
范例:有一组数据,求人均月收入最高家庭
在这里随机产生了一组测试数据,文件名为 income.txt
。
1 3 4490
2 5 3896
3 4 3112
4 4 4716
5 4 4578
6 6 5399
7 3 5089
8 6 3029
9 4 6195
10 5 5145
说明:上面的三列数据分别是家庭编号、家庭人数、家庭月总收入。
分析:为了求月均收入最高家庭,需要对后面两列数进行除法运算,即求出每个家庭的月均收入,然后按照月均收入排序,找出收入最高家庭。
实现:
#!/bin/bash
# gettopfamily.sh
[ $# -lt 1 ] && echo "please input the income file" && exit -1
[ ! -f $1 ] && echo "$1 is not a file" && exit -1
income=$1
awk '{
printf("%d %0.2f\n", $1, $3/$2);
}' $income | sort -k 2 -n -r
说明:
[ $# -lt 1 ]
:要求至少输入一个参数,$#
是 Shell 中传入参数的个数[ ! -f $1 ]
:要求输入参数是一个文件,-f
的用法见test
命令,help test
income=$1
:把输入参数赋给 income 变量,再作为awk
的参数,即需处理的文件awk
:用文件第三列除以第二列,求出月均收入,考虑到精确性,保留了两位精度sort -k 2 -n -r
:这里对结果的awk
结果的第二列-k 2
,即月均收入进行排序,按照数字排序-n
,并按照递减的顺序排序-r
。
演示:
$ ./gettopfamily.sh income.txt
7 1696.33
9 1548.75
1 1496.67
4 1179.00
5 1144.50
10 1029.00
6 899.83
2 779.20
3 778.00
8 504.83
补充:之前的 income.txt
数据是随机产生的。在做一些实验时,往往需要随机产生一些数据,在下一小节,我们将详细介绍它。这里是产生 income.txt
数据的脚本:
#!/bin/bash
# genrandomdata.sh
for i in $(seq 1 10)
do
echo $i $(($RANDOM/8192+3)) $((RANDOM/10+3000))
done
说明:上述脚本中还用到seq
命令产生从1到10的一列数,这个命令的详细用法在该篇最后一节也会进一步介绍。