Linux内的bc计算器是一个非常强大的计算器,内置了一套类似C语言的语法。学习bc可以不用高级编程语言的情况下解决一系列的问题。但是目前网上没有找到很好的中文教程,在此自己写一个,方便以后查阅。
最基本的是日常使用的计算,这样子和Windows自带的计算器没有太大的差别,不过一目了然的输入和运算优先级的支持还是要强大很多。具体方法如下:
bc
1+2*3-5*2
-3
注:上述示例意为输入bc后启动,输入1+2*3-5*2
后按回车,得到结果-3
但是在输入5/4
的时候,会得到1。这是因为bc有若干内置变量,其中的scale
内置变量指定运算要用到的小数点后的位数,默认为0,即只支持指定运算。因此,在运算前设置scale=2
,就会得到正确的结果啦!^_^
总共有4个内置变量,为:
变量名称 | 作用 |
---|---|
scale | 指定运算要用到的小数点后的位数 |
ibase | 指定输入的进制数 |
obase | 指定输出的进制数 |
last或者. | 最近打印的数字(扩展) |
指定输入输出进制的情况下就能轻松处理进制转换了!比如二进制转16进制:
ibase=2
obase=16
1010
101
这是怎么回事?不是应该是A吗?原因在于:先指定了二进制的输入,在指定obase变量的时候,16也被认为是二进制的输入啦!在二进制的输入情况下,所有的非0全部认为是1,于是16被看作是11,即3进制。1010对应十进制是10,101对于的3进制也是10。就是这样啦。
正确的方法应该是先指定obase,如下:
obase=16
ibase=2
1010
A
bc可以支持用户自定义变量。变量有2种类型,数字和数组。注意,不支持字符串类型的变量,数组也只能是数字的数组。至于变量的赋值,和C语言语法一致:
var_name = 123;
array_name[13] = 2;
在以上的例子中,声明了一个var_name的变量,赋值为123。声明了一个名为array_name的数组,它的0到12号元素均为0,13号元素为2。注意,分号可有可无,但是如果是写脚本程序的话,写上为好。
所有的变量在未赋值时均为0。
如果在变量前面加入auto,则表明是局部变量,否则为全局变量。(函数的参数为局部变量,是例外情况)
bc支持以下几种运算:
运算符 | 解释 |
---|---|
++,– | 同C语言,也分前置和后置 |
+,-,*,/ | 同C语言 |
+=,-=,*=,/= | 同C语言 |
%,%= | 取余。当scale=0时同C语言,否则见下 |
^ | 指数运算(只支持整数的指数) |
<,<=,>,>=,==,!= | 同C语言 |
!, &&, || | 同C语言 |
注意取余运算,当scale不为0时,如,scale=2,则:
4 % 3 = 0.01
这是由于4/3=1.33,4-3*1.33=0.01
另外,bc还有4个内置函数,分别是:
名称 | 作用 |
---|---|
length | 得到一个变量的有效数字个数 |
read | 得到用户输入 |
scale | 不同于内置变量,这个内置函数意为得到变量小数点后的数字的个数 |
sqrt | 开方运算 |
具体示例参见后面的程序。
主要的语法完全可以参照C语言。注意的是:当一个值没有被赋予变量时,会直接输出,因此可以通过直接输入字符串的方式得到输出。字符串以""
包裹。
有以下的关键字:
关键字 | 作用 |
---|---|
输出变量,后面是一个列表,以, 分隔,会将其依次输出,注意,不会输出换行符,需要自己添加”\n”。关于转义字符,和C语言相同。 |
|
{} | 大括号构成语言块,作用和C语言相同 |
if,else | 用法和C语言相同 |
for | 和C语言相同 |
break | 和C语言相同 |
continue | 和C语言相同 |
while | 和C语言相同 |
return | 和C语言相同 |
halt | 当运行到此语句时,程序退出 |
函数的声明方法:
define function_name(var_list) {
function_body;
}
如:
/*递归版本的阶乘函数*/
define factorial(x) {
if (x <= 1)
return 1;
return x * factorial(x-1);
}
factorial(5)
120
当函数无返回值时,执行会有问题。此时需要在define和函数名之间加入void关键字。为:
define func_a() {
print "this is func a\n";
}
define void func_b() {
print "this is func b\n";
}
func_a();
this is func_a
0
func_b();
this is func_b
有以下的操作符:
名称 | 内容 |
---|---|
limits | 输入后会得到本版本bc的各个最大值 |
quit | 退出程序 |
warranty | 得到一个更多的版本信息 |
选项内容如下:
内容 | 作用 |
---|---|
-l | 提前加载数学库,并将scale设置为20 |
-q | 安静模式,不输出欢迎信息 |
-v | 输出版本信息 |
-s | 使用POSIX标准bc语言,而非GNU扩展语言 |
数学函数库中,有以下几个常用函数:
函数名 | 内容 |
---|---|
s(x) | sin函数 |
c(x) | cos函数 |
a(x) | atan函数 |
l(x) | ln函数 |
e(x) | e的x次幂 |
j(n, x) | x的n阶贝塞尔函数,(n为整数) |
在bash
中可以使用以下方法指定 π 的值给环境变量:
pi=${echo "scale=10;4*a(1)" | bc -l}
以下是man手册中,实现的e(x)的函数。没有使用GNU扩展语法,使用的是POSIX的标准bc语法。思路是由公式:
scale = 20
define e(x) {
auto a, d, e, f, i, m, v, z
if (x < 0) {
m = 1
x = -x
}
/* Precondition x. */
z = scale;
scale = 4 + z + .44*x;
while (x > 1) {
f += 1;
x /= 2;
}
/* Initialize the variables. */
v = 1 + x
a = x
d = 1
for (i=2; 1; i++) {
e = (a *= x) / (d *= i)
if (e == 0) {
if (f > 0) while (f--) v = v*v;
scale = z
if (m) return (1/v);
return (v/1);
}
v += e
}
}
其中,v/1可能看着有些奇怪。这是将变量截取到当前的scale。比如:
scale=5
a=0.123456789
a
.123456789
a /= 1
a
.12345
问题如下:
假设一年以后开始存养老金,每年将工资的2%存入银行帐户,年利率8%,去年的工资为50000元,并且每年4%速度增长。假如你40年后退休,到那时一共存了多少钱?
可以写一个如下的脚本:
#!/usr/bin/bc -q
scale = 10
salary = 50000;
save = 0.02;
increase = 0.04;
interest = 0.08;
sum_save = 0;
print "Please input num of years: ";
year = read();
for (i = 0; i < year; i++) {
sum_save += salary * save;
sum_save *= 1 + interest;
salary *= 1 + increase;
}
scale = 2;
sum_save /= 1;
print "After ", year, " years, you save money ", sum_save, "\n"
运行结果为:
Please input num of years:
40
After 40 years, you save money 456934.52
总体来说,仅仅使用bc就可以解决一系列的计算问题啦!