这是我在codewar上遇到的一个题,我用我自己的方法做出了解答,如下:
1 #!/bin/bash2 3 distance=`echo "$1*10000"|bc|cut -d"." -f1`4 a=05 n=16 7 if [ $distance -le 0 ];then8 echo None9 else 10 while [ $n -lt $distance ] ; do 11 let a++ 12 n=$((2**a)) 13 done 14 echo $a 15 fi 16 17 重庆-刘勇 2018/11/15 23:29:25
在这里因为不知道小数点的处理办法,所以用了看起来很愚笨的cut来切割,直到通过后可以看到其他人的答案。有一种写法,里面解决了很多小数点的问题,所以我记录了下来,如下:
1 distance=$12 paper="0.0001"3 count=04 if (( $(echo "$distance<0" | bc -l) ))5 then 6 echo "None"7 else8 while (( $(echo "$paper<$distance" | bc -l) )) 9 do 10 paper=$(echo "scale=4;$paper*2" | bc ) 11 count=$((count+1)) 12 done 13 echo $count 14 fi
第一个问题:
scale的用法:
1、显示小数点后的位数:
[root@centos7 ~]#echo "scale(1.234567)"|bc 6 [root@centos7 ~]#echo "scale(1.234000)"|bc 6
他是会识别后面的0的哪怕无意义。
length是计算数值长度的另一个参数,他会计算小数点前后所有的位数,但是有个地方需要注意,当这个小数点前只有一个0的时候,它是不计算这个0的
[root@centos7 ~]#echo "length(1.234567)"|bc 7 [root@centos7 ~]#echo "length(0.123456)"|bc 6
2、截取小数点的位数:
[root@centos7 ~]#echo "scale=3;1.23456*10"|bc 12.34560 [root@centos7 ~]#echo "scale=3;1.23456*10/1"|bc 12.345 [root@centos7 ~]#echo "scale=3;(1.23456+10)/1"|bc 11.234
从此代码可以看到,scale的生效和/1有绝对的关系,没有这个格式会导致scale无效,无论是加减法,或者乘法,经过测试以后发现最后的一步计算都必须以除法结尾,最简单的就是/1了,当然本来最后一步就是除法就可以忽略了。
利用bc进行大小比较
echo "1>2"|bc
这里一定一定要注意的是,这个比较结果就是0或1,而不是代表true或false,因而不能用于if后的条件判断!切记切记
但是在添加(())以后可以进行比较判断。注意看他们的结果,在添加了(())后,对表达式进行了真假判断
[root@centos7 ~]#(( $(echo "1>2"|bc) ))
[root@centos7 ~]#echo $?
1
[root@centos7 ~]#echo "1>2"|bc
0
[root@centos7 ~]#echo "1<2"|bc
1
[root@centos7 ~]#(( $(echo "1<2"|bc) ))
[root@centos7 ~]#echo $?
0
bc还可以方便快捷的进行进制转换:
标准格式: echo "obase=2;ibase=16;FFFF" | bc ,obase表示输出的进制,ibase表示输入的进制,默认输入10位,所以也有简写为:echo "obase=2;123"|bc ,表示为输入10进制123,输出2进制
但是有一个地方需要特别注意,格式中obase必须在前,ibase在后,否则会有计算错误,如下
[root@centos7 ~]#echo "ibase=8;obase=16;17"|bc 11 [root@centos7 ~]#echo "ibase=10;obase=16;17"|bc 11 [root@centos7 ~]#echo "obase=16;ibase=8;17"|bc F [root@centos7 ~]#echo "obase=16;ibase=8;10"|bc 8 [root@centos7 ~]#echo "obase=16;ibase=8;117"|bc 4F [root@centos7 ~]#echo "ibase=8;obase=16;117"|bc 59