科學計數法使用e標識數值,將科學計算學轉化為數字的思路:按e右邊的數字移動小數點位數。e右邊的數字如果是負數,則向左移動小數點。示例如下:
1.2345678e2 = 123.45678 1.2345678e-2 = 0.012345678 1.7615562e+06 = 1761556.2 1.87982e7 = 18798200 1e3 = 1000
那么在shell中,如何轉化科學計數法為數字呢,方法如下:這里以"1.7615562e+06" (或者1.7615562e6)為示例:
[root@kevin ~]# echo "1.7615562e6"| gawk '$1=strtonum($1)' 1.76156e+06
1)科學計數法轉為十進制
[root@kevin ~]# printf "%f" 1.7615569e+06 1761556.900000 [root@kevin ~]# echo "1.7615569e+06"| awk '{printf("%f",$0)}' 1761556.900000 [root@kevin ~]# echo "1.7615569e+03"| awk '{printf("%f",$0)}' 1761.556900 [root@kevin ~]# echo "1.7615569e+04"| awk '{printf("%f",$0)}' 17615.569000 [root@kevin ~]# echo "1.7615569e-6"| awk '{printf("%f",$0)}' 0.000002 [root@kevin ~]# echo "1.7615569e-4"| awk '{printf("%f",$0)}' 0.000176 [root@kevin ~]# echo "1.7615569e-3"| awk '{printf("%f",$0)}' 0.001762 [root@kevin ~]# echo "1.7615569e-2"| awk '{printf("%f",$0)}' 0.017616 需要注意: 這種方法,轉化結果中小數點后面都保留6位: 1)e后面的數字若是正數,則小數點后面要保留6位,不夠的話,用0補上。 2)e后面的數字若是負數,則小數點后面要保留6位,多的話,此時按照四舍五入,保留6位。
2)科學計數法轉為十進制並保留兩位小數
[root@kevin ~]# echo "1.7615569e+06"| awk '{printf("%.2f",$0)}' 1761556.90 保留三位小數 [root@kevin ~]# echo "1.7615569e+06"| awk '{printf("%.3f",$0)}' 1761556.900
3)科學計數法轉為十進制並取整
[root@kevin ~]# echo "1.7615569e+06"|awk '{printf("%d",$0)}' 1761556 [root@kevin ~]# echo "1.7615569e3"|awk '{printf("%d",$0)}' 1761 [root@kevin ~]# echo "1.7615569e02"|awk '{printf("%d",$0)}' 176
4)科學計數法轉十進制並四舍五入取整
[root@kevin ~]# echo "1.7615569e+06"| awk '{printf("%d",$0+0.5)}' 1761557 [root@kevin ~]# echo "1.7615563e+06"| awk '{printf("%d",$0+0.5)}' 1761556
《擴展1》
5)如何將小數點后無用的0去掉, 可以參考: 日常運維的Shell腳本中截取字符串的做法,即用變量擴展的方式
[root@kevin ~]# echo "1.7615569e+06"| awk '{printf("%f",$0)}' 1761556.900000 [root@kevin ~]# var=$(echo "1.7615569e+06"| awk '{printf("%f",$0)}') [root@kevin ~]# echo ${var%%0*} 1761556.9
或者使用sed方法也可以
[root@kevin ~]# echo "1.7615569e+06"| awk '{printf("%f",$0)}' 1761556.900000 [root@kevin ~]# var=$(echo "1.7615569e+06"| awk '{printf("%f",$0)}') [root@kevin ~]# echo "$var"|sed 's/0*$//' 1761556.9 [root@kevin ~]# echo "1.7615569e+06"| awk '{printf("%f",$0)}'| sed 's/0*$//' 1761556.9
《擴展2》
6)sed去除掉小數點之后的字符
[root@kevin ~]# echo "kevin.123"|sed "s/\.*//g" kevin123 \..*代表了小數點之后的1到多個 [root@kevin ~]# echo "kevin.123"|sed "s/\..*//g" kevin [root@kevin ~]# echo "kevin_123"|sed "s/\_*//g" kevin123 [root@kevin ~]# echo "kevin_123"|sed "s/\_.*//g" kevin 命令解釋: *代表0到多個。故\.*只能替換掉小數點變成空。\_*同理。 .*代表1到多個。故\..*將小數點后的全部去掉了。\_.*同理。
《擴展3》
7)shell中的數字計算說明
1)bc方法 bc是比較常用的linux計算工具了,而且支持浮點運算: [root@kevin ~]# a=`echo 1+1 | bc` [root@kevin ~]# echo $a 2 這種方法沒法解決浮點數運算的精度問題,如下幾種浮點數計算情況就傻X了! [root@kevin ~]# a=`echo 1+1 | bc` [root@kevin ~]# echo $a 2 [root@kevin ~]# b=`echo "1.2*1.2" | bc` [root@kevin ~]# echo $b 1.4 [root@kevin ~]# c=`echo "5.0/3.0" | bc` [root@kevin ~]# echo $c 1 [root@kevin ~]# d=`echo "scale=2;5.0/3.0" | bc` [root@kevin ~]# echo $d 1.66 [root@kevin ~]# e=`echo "scale=2;5.0/6.0" | bc` [root@kevin ~]# echo $e .83 2)expr方法 不支持浮點數計算,這是個坑,而且要注意數字與運算符中的空格。 [root@kevin ~]# a=`expr 1+1` [root@kevin ~]# echo $a 1+1 [root@kevin ~]# a=`expr 1 + 1` [root@kevin ~]# echo $a 2 [root@kevin ~]# b=`expr 10 / 2` [root@kevin ~]# echo $b 5 3)$(())方法 同expr,不支持浮點數運算 [root@kevin ~]# a=$((1+1)) [root@kevin ~]# echo $a 2 [root@kevin ~]# b=$((1 + 3 )) [root@kevin ~]# echo $b 4 4)let方法 不支持浮點數運算,而且不支持直接輸出,只能賦值 [root@kevin ~]# let a=1+1 [root@kevin ~]# echo $a 2 [root@kevin ~]# let b=50/5 [root@kevin ~]# echo $b 10 [root@kevin ~]# let c=1.2*2 -bash: let: c=1.2*2: syntax error: invalid arithmetic operator (error token is ".2*2") 5)awk方法 普通的運算: [root@kevin ~]# a=`echo | awk '{print 1.0/2.0}'` [root@kevin ~]# echo $a 0.5 控制精度: [root@kevin ~]# b=`echo | awk '{printf("%.2f",1.0/2.0)}'` [root@kevin ~]# echo $b 0.50 傳遞參數: [root@kevin ~]# c=`echo | awk -v a=1 -v b=3 '{printf("%.4f",a/b)}'` [root@kevin ~]# echo $c 0.3333 awk結合BEGIN(小數點后面保留6位) [root@ss-server ~]# awk 'BEGIN{printf "%.2f%%\n",(87/500)*100}' 17.40% [root@ss-server ~]# awk 'BEGIN{printf "%.2f%%\n",(100/300)*100}' 33.33% 綜合來看,還是awk的方法最靠譜,其他的方式都有相應問題。所以推薦在日常維護場景下使用awk來搞數學計算。