一步步打造自己的linux命令行计算器
2018-10-13 18:19
375 查看
相信很多人,在工作中会需要使用到计算器。一般的做法是,打开并使用系统自带的计算器。
这种做法可能对我来说,有如下几个问题。
GNU bc支持高精度数字和多种数值类型(例如二进制、十进制、十六进制)的输入输出。
bc的交互式使用方式,运行bc,进入交互模式。在交互模式中输入表达式,回车即可获得结果。需要退出时输入quit退出即可。
bc的非交互式使用方式,通过管道将表达式传入。
使用效果如下
我们可以让mycalc.sh先处理下表达式中的数字,约定0x开头为十六进制,不带前缀为十进制,0o开头为八进制,0b开头为二进制。
mycalc先将所有参数转换成统一的进制,如十进制,然后计算表达式的值,最终将结果再以多种进制的形式输出。这样我们就不同手工处理进制问题了。
至于输出,为了方便起见,可以多种进制一起输出,需要哪个用哪个即可
这里就不贴代码了,有兴趣可移步github https://github.com/zqb-all/smartbc,我们接着往下看,后面有更简单的方式。
使用示例
在命令行中,输入python,进入交互模式,即可像bc一样执行表达式,得到结果。更棒的是,原生支持混合进制,不需要自己写代码预处理表达式了。简单可靠。
代码及使用示例
比如,当需要核对寄存器,检查某个bit时,一个个去数二进制的第19位,是很费眼睛的一件事。
这个时候就需要更加直观的输出,可以一眼看到某个bit是0还是1。
那好办,给二进制加上下标好了。如下
代码
这种做法可能对我来说,有如下几个问题。
- 太慢。每次需要打开计算器,然后改成编程模式,手工选择进制,再使用输入表达式进行计算。
- 需要切换窗口。编程时经常是在终端中,使用GUI计算器则意味着要离开终端,计算完毕再切换回来。
- 无法使用混合进制表达式。混合进制的意思是,在一个表达式中同时使用多种进制,如“0x10 * 10”表示十六进制的0x10乘以十进制的10。
命令行计算器,调用bc
只需经过简单的搜索,便可以了解到,linux中原生提供了一个命令行计算器 GNU bc。GNU bc支持高精度数字和多种数值类型(例如二进制、十进制、十六进制)的输入输出。
bc的交互式使用方式,运行bc,进入交互模式。在交互模式中输入表达式,回车即可获得结果。需要退出时输入quit退出即可。
bc的非交互式使用方式,通过管道将表达式传入。
使用效果如下
zhuangqiubin@zhuangqiubin-PC:~$ bc bc 1.07.1 Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. 1+2 3 quit zhuangqiubin@zhuangqiubin-PC:~$ echo "1+2" | bc 3OK,get到了命令行计算器的新技能了,但每次进入交互模式或者手工输入“echo 表达式 | bc ”都感觉略麻烦。那这个时候,就需要脚本,写个mycalc.sh好了
zhuangqiubin@zhuangqiubin-PC:~$ cat mycalc.sh #!/bin/bash echo "$@" | bc zhuangqiubin@zhuangqiubin-PC:~$ ./mycalc.sh 1+2 3再把mycalc.sh拷贝到可访问的目录下,如
sudo mv mycalc.sh /usr/bin对于没有sudo权限的情况,那也可以变通下
mkdir -p ~/usr/bin mv mycalc.sh ~/usr/bin echo 'export PATH=$HOME/usr/bin:$PATH' >> ~/.bashrc source ~/.bashrc再alias一个顺手的命令名,比如拼音jisuan
echo "alias jisuan='mycalc.sh'" >> ~/.bashrc更多bc的用法,可以通过man bc查看,网上也有许多介绍资料。
解决进制问题
bc仍然需要手工指定进制,在表达式前,使用ibase参数和obase参数指定输入输出的进制。并且不支持混合进制,因为ibase每次只能指定一种进制。zhuangqiubin@zhuangqiubin-PC:~$ echo "10+10" | bc 20 zhuangqiubin@zhuangqiubin-PC:~$ echo "ibase=16;10+10" | bc 32但我们既然已经有了一个包装脚本mycalc.sh,那是不是可以把进制转换的工作交给它呢,当然可以。
我们可以让mycalc.sh先处理下表达式中的数字,约定0x开头为十六进制,不带前缀为十进制,0o开头为八进制,0b开头为二进制。
mycalc先将所有参数转换成统一的进制,如十进制,然后计算表达式的值,最终将结果再以多种进制的形式输出。这样我们就不同手工处理进制问题了。
至于输出,为了方便起见,可以多种进制一起输出,需要哪个用哪个即可
这里就不贴代码了,有兴趣可移步github https://github.com/zqb-all/smartbc,我们接着往下看,后面有更简单的方式。
使用示例
zhuangqiubin@zhuangqiubin-PC:~$ type jisuan jisuan 是 `~/mywork/mygithub/smartbc/smartbc' 的别名 zhuangqiubin@zhuangqiubin-PC:~$ jisuan 10+10 Original EQUATION: 10+10 Decimal EQUATION: 10+10 base2 : 10100 base8 : 24 base10: 20 base16: 14 zhuangqiubin@zhuangqiubin-PC:~$ jisuan 10+0x10 Original EQUATION: 10+0x10 Decimal EQUATION: 10+16 base2 : 11010 base8 : 32 base10: 26 base16: 1A
更好的实现,使用python
以上基于bc的计算器,已经可以满足我的需求了,也使用了一段时间。但其实还有更好的实现方式,使用python。在命令行中,输入python,进入交互模式,即可像bc一样执行表达式,得到结果。更棒的是,原生支持混合进制,不需要自己写代码预处理表达式了。简单可靠。
代码及使用示例
zhuangqiubin@zhuangqiubin-PC:~$ type jisuan jisuan 是 `~/.pycalc.py' 的别名 zhuangqiubin@zhuangqiubin-PC:~$ cat ~/.pycalc.py #!/usr/bin/env python2 import sys equation=sys.argv[1] result=eval(equation) if isinstance(result, (float)): print "Attention:only base10 is float, others change to int before type" print "equation:",sys.argv[1] print "base2 : ",str(bin(int(result))) print "base8 : ",str(oct(int(result))) print "base10: ",str((result)) print "base16: ",str(hex(int(result))) zhuangqiubin@zhuangqiubin-PC:~$ jisuan 10+10 equation: 10+10 base2 : 0b10100 base8 : 024 base10: 20 base16: 0x14 zhuangqiubin@zhuangqiubin-PC:~$ jisuan 10+0x10 equation: 10+0x10 base2 : 0b11010 base8 : 032 base10: 26 base16: 0x1a
更多输出格式
一般,输出十六进制,十进制,二进制三种结果就足够用了。但如果有特殊需求,也可自己拓展。比如,当需要核对寄存器,检查某个bit时,一个个去数二进制的第19位,是很费眼睛的一件事。
这个时候就需要更加直观的输出,可以一眼看到某个bit是0还是1。
那好办,给二进制加上下标好了。如下
代码
#!/usr/bin/env python2 import sys def formatBinString(num): result='bit: ' result_index='index: ' num_len=len(num) if num_len > 32: return "" for i in num: num_len-=1 result+=i result+=' | ' result_index+=str(num_len).zfill(2) result_index+='| ' return result+'\n'+result_index equation=sys.argv[1] result=eval(equation) if isinstance(result, (float)): print "Attention:only base10 is float, others change to int before type" print "equation:",sys.argv[1] print "" print "base2 : ",str(bin(int(result))) print "base8 : ",str(oct(int(result))) print "base10: ",str((result)) print "base16: ",str(hex(int(result))) print "" print formatBinString(str(bin(int(result))[2:].zfill(32)))效果
zhuangqiubin@zhuangqiubin-PC:~$ jisuan 10+0x10 equation: 10+0x10 base2 : 0b11010 base8 : 032 base10: 26 base16: 0x1a bit: 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | index: 31| 30| 29| 28| 27| 26| 25| 24| 23| 22| 21| 20| 19| 18| 17| 16| 15| 14| 13| 12| 11| 10| 09| 08| 07| 06| 05| 04| 03| 02| 01| 00|
相关文章推荐
- 一步步打造自己的代码生成器
- Android -- 从源码的角度一步步打造自己的TextView
- 一步步打造自己的分页控件--1
- 一步步打造自己的分页控件--4
- 一步步打造自己的代码生成器---获取数据库框架信息A
- 一步步打造自己的通用上拉加载布局
- 一步步打造自己的分页控件--2
- Cacti高级应用--打造自己的Cacti模板
- (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)
- 内核编译打造自己喜欢的linux
- 【打造自己的计算机】编程模型
- Node.js中REST API使用示例——基于云平台+云服务打造自己的在线翻译工具
- 一步步实现自己的ORM
- 简单打造自己的UCE
- 打造自己的reset.css
- Android 使用Vitamio打造自己的万能播放器(3)――本地播放(主界面、播放列表)
- 结合博客园提供的免费功能服务,打造自己专业友善的软件功能组件(主要是思想)
- Android 使用Vitamio打造自己的万能播放器(10)―― 本地播放 (缩略图、视频信息、视频扫描服务)
- 【转】打造人脉不如打造自己
- 打造自己称手的代码