#+TITLE: emacs-calculator使用说明 #+URL: http://nullprogram.com/blog/2009/06/23/ #+AUTHOR: lujun9972 #+CATEGORY: calc #+DATE: [2016-07-08 五 22:49] #+OPTIONS: ^:{} 你知道[[http://www.gnu.org/software/emacs/calc.html][Emacs自带有一个计算器吗]]? 我的天,一个完整的计算器!听起来很不可意思,不是吗? 事实上, 这可不仅仅是个简单的计算器而已, 这是一个[[http://en.wikipedia.org/wiki/Computer_algebra_system][计算机代数系统]]! 虽说官方只是称呼它为一个计算器,但这只是一种谦虚的说法,我想恐怕有很多人因此而忽视了它. 我自己也是在通读Emacs manual时才发现它的,而且当时也差点略过了它. 你有看过几年前Will Wright为孢子游戏所做的展示么? 玩家一开始只是个单细胞生物,后来发展出一个横跨星际的文明. Will Wright开始时只展示了一个显微镜下的细胞. 没人知道这个什么样的游戏,而随着尺度的增加,从细菌到动物,从动物到出现文明,从出现文件到实现太空旅行,在星际间旅行到星系间旅行,引起了观众一次次的强烈反响. 就像它的广告语说的:"还没完呢!!!" 随着我不断的深入Emacs calc manual,我一次次的感叹于它的功能之强. 每一页说明都在告诉我:"还没完呢!!!". 我这里仅仅对对其某些特征进行讲解. 要想获得一个全面的了解,你需要阅读calc manual. manual中甚至还有一些练习来展示一些陷阱和一些有趣的特征交互. 按下 =C-x * c= 或 =M-x calc= 启动calc. 会显示出两个新窗口(Emacs意义下的窗口),一个是计算器,另一个显示操作历史. 首先,这个计算器是基于栈操作的,它的基础用法是采用逆波兰表示法. 栈垂直向下生长. 输入数字然后回车就会将数字入栈. 输入数字后也可以直接输入运算符而无需每次都回车. 由于减号(-)被用于表示减法运算符,因此使用下划线(_)来表示负数. 下面是一个例子,依次入栈3, 4, 10: #+BEGIN_EXAMPLE 3: 3 2: 4 1: 10 . #+END_EXAMPLE 10位于栈顶(因此它的前面的编号为"1:"), 当我们输入 =*= 时,最顶部的两个元素会相乘: #+BEGIN_EXAMPLE 2: 3 1: 40 . #+END_EXAMPLE calc支持无限长度的整型,因此你可以使用超大的数而不会有精度丢失. 例如我们计算一下2^200: #+BEGIN_EXAMPLE 2: 2 1: 200 . #+END_EXAMPLE 按下 =^=, #+BEGIN_EXAMPLE 1: 1606938044258990275541962092341162602522202993782792835301376 . #+END_EXAMPLE 还没完!!! Calc支持复数,方法是将实部与虚部成对放入括号内,像这样 =(real, imaginary)=. 可以对复数进行任意运算,就跟其他数一样. 例如计算 ~-1 + 2i~ 减去 ~4 + 2i~, #+BEGIN_EXAMPLE 2: (-1, 2) 1: (4, 2) . #+END_EXAMPLE 按下 =-= 作减法, #+BEGIN_EXAMPLE 1: -5 . #+END_EXAMPLE 然后按下 =Q= 调用平方根函数计算平方根. #+BEGIN_EXAMPLE 1: (0., 2.2360679775) . #+END_EXAMPLE 你还可以按下 =p= 来设置计算的精度. 默认精度为12位. 例如计算 ~1 / 7~: #+BEGIN_EXAMPLE 1: 0.142857142857 . #+END_EXAMPLE 我们将精度调整为50位后,再计算一次: #+BEGIN_EXAMPLE 2: 0.142857142857 1: 0.14285714285714285714285714285714285714285714285714 . #+END_EXAMPLE 数字能以各种计数法的方式来表示,例如定点计数法,科学计数法,工程计数法. 可以在不同计数法之间切换而不会丢失任何信息(数的存储与显示是独立的). 还没完呢!!! 我们还可以用分数的形式表示有理数. 格式是 =分子:分母=. #+BEGIN_EXAMPLE 3: 1:7 2: 3:13 1: 17:29 . #+END_EXAMPLE 它们的累积以最低层的形式来显示(And multiply them all together, which displays in the lowest form), #+BEGIN_EXAMPLE 1: 51:2842 . #+END_EXAMPLE There is a mode for working in these automatically. 还没完呢!!! 我们还能修改基数. 要输入一个其他基数的数字,只需要以基数和 =#= 为前缀即可. 例如我们是这样输入以2为积的29的: #+BEGIN_EXAMPLE 2#11101 #+END_EXAMPLE 可以通过 =d r= 修改显示的基数. 例如假设栈中的数字为29(10进制),则转换成以4为基数则是: #+BEGIN_EXAMPLE 1: 4#131 . #+END_EXAMPLE 转换为16进制为: #+BEGIN_EXAMPLE 1: 16#1D . #+END_EXAMPLE 转换为36进制为: #+BEGIN_EXAMPLE 1: 36#T . #+END_EXAMPLE 还没完呢!!! 我们也可以直接输入代数表达式,方法是以单引号(')开头. 表达式中甚至还可以带符号. 注意: 这些表达式不是以逆波兰表示法录入的. #+BEGIN_EXAMPLE 1: a^3 + a^2 b / c d - a / b . #+END_EXAMPLE 按下 =d B= 可以进入"big"模式,在此模式下更易阅读: #+BEGIN_EXAMPLE 2 3 b a a 1: a + ---- - - c d b . #+END_EXAMPLE 我们还可以为变量赋值来计算表达式. 例如使用 "evaluates-to" 运算符将a的值赋为10可以得到下列结果: #+BEGIN_EXAMPLE 2 3 a b a 100 b 10 1: a + ---- - - => 1000 + ----- - -- c d b c d b . #+END_EXAMPLE 还没完呢!!! Calc支持向量类型,可以用来表示向量,矩阵并进行线性代数运算. 方法是将各元素置入方括号内,[] #+BEGIN_EXAMPLE 2: [4, 1, 5] 1: [ [ 1, 2, 3 ] [ 4, 5, 6 ] [ 6, 7, 8 ] ] . #+END_EXAMPLE 然后计算该向量与矩阵的点积与叉积. #+BEGIN_EXAMPLE 2: [38, 48, 58] 1: [ [ -14, -18, -22 ] [ -19, -18, -17 ] [ 15, 18, 21 ] ] . #+END_EXAMPLE Calc支持你能想到的任何矩阵与数组运算,包括map和reduce(而且你还能定义自己的应用表达式) 可以用Calc来求解线性方程. 基于a和b算出x和y的值. #+BEGIN_EXAMPLE x + a y = 6 x + b y = 10 #+END_EXAMPLE 我们这么输入它(注意我们我们这里用了符号), #+BEGIN_EXAMPLE 2: [6, 10] 1: [ [ 1, a ] [ 1, b ] ] . #+END_EXAMPLE 按下除法运算符 #+BEGIN_EXAMPLE 4 a 4 1: [6 + -----, -----] a - b b - a . #+END_EXAMPLE 还没完呢!!! 若安装了gnuplot的话,还能用Calc创建图形. We can give it two vectors, or an algebraic expression. 只需要很少的几次按键,都能画出下面的 =sin(x)= 和 =x cos(x)= 的图形来. [[http://nullprogram.com/img/emacs/calc-plot.png]] 还没完呢!!! Calc还支持一种叫做HMS的类型,该类型可以表示时间和角度. 例如可以表示像2小时30分4秒这类东西. #+BEGIN_EXAMPLE 3: 2@ 30' 4" 2: 4@ 22' 13" 1: 1@ 2' 56" . #+END_EXAMPLE 当然我们可以对其进行常见的计算. 让我们将这些时间都雷加起来: #+BEGIN_EXAMPLE 1: 7@ 55' 13" . #+END_EXAMPLE 我们可以将之与弧和度进行相互转换. 还没完呢!!! Calc本身也有时间类型,方法是将时间填入尖括号内,<>(需在代数模式下输入). 要输入时间真的很灵活. 若像输入当前时间,只需按下 =t N= 即可. #+BEGIN_EXAMPLE 1: <6:59:34pm Tue Jun 23, 2009> . #+END_EXAMPLE 这时,输入的数字会作为天来看待,例如加4的结果是: #+BEGIN_EXAMPLE 1: <6:59:34pm Sat Jun 27, 2009> . #+END_EXAMPLE 它还支持与前面说的HMS格式的值进行计算,例如减去 2@ 3' 15"的结果为: #+BEGIN_EXAMPLE 1: <4:56:32pm Sat Jun 27, 2009> . #+END_EXAMPLE 还没完呢!!! Calc还有一种模形式用于进行求模运算. 例如,输入 =17 mod 24=, #+BEGIN_EXAMPLE 1: 17 mod 24 . #+END_EXAMPLE 加上10,得到结果为 #+BEGIN_EXAMPLE 1: 3 mod 24 . #+END_EXAMPLE 模形式对于要计算 =n^p mode M= 这种形式的运算时,特别方便. 例如,要计算 =3^100000 mod 24=,一般的方法时先计算 =3^100000=,再取模. 由于 =3^100000= 是一个很大的数,因此计算这个中间步骤十分昂贵. 使用模形式能够不必实际地计算出 =3^100000= 的值来. 还没完呢!!! Calc还能进行单位转换. 我这会儿用的Emacs版本(22.3.1)支持159种不同的格式. 例如,我输入65mph. #+BEGIN_EXAMPLE 1: 65 mph . #+END_EXAMPLE 按下 =u c= 将其单位转换为 ~米每秒(m/s)~ #+BEGIN_EXAMPLE 1: 29.0576 m / s . #+END_EXAMPLE Calc还支持不同单位进行混用. 例如我输入3立方米: #+BEGIN_EXAMPLE 3 1: 3 m . #+END_EXAMPLE 可以转换成加仑: #+BEGIN_EXAMPLE 1: 792.516157074 gal . #+END_EXAMPLE 我所在的实验室白天的时候连接不上互联网, 因此当我需要做各种转换时,Emacs是不可缺少的. 光速也是一种单位,我可以将 =1c= 转换为米每秒: #+BEGIN_EXAMPLE 1: 299792458 m / s . #+END_EXAMPLE 还没完呢!!! 就像我说过的, Calc实现了一个计算机代数系统, 因此它能够进行符号运算. 还记得之前的那些代数表达式么? 我可以对它们进行运算. 让我们先输入一些表达式. #+BEGIN_EXAMPLE 3: ln(x) 2 a x 2: a x + --- + c b 1: y + c . #+END_EXAMPLE 将最顶上两个表达式想乘,然后加上第三个表达式得到答案: #+BEGIN_EXAMPLE 2 a x 1: ln(x) + (a x + --- + c) (y + c) b . #+END_EXAMPLE 按下 =a x= 对表达式进行扩展,然后按下 =a s= 简化表达式: #+BEGIN_EXAMPLE 2 a x y 2 a c x 2 1: ln(x) + a y x + ----- + c y + a c x + ----- + c b b . #+END_EXAMPLE 下面介绍Calc其中最酷的一项功能:微积分. 按下 =a d= 可以对x求微分: #+BEGIN_EXAMPLE 1 a y a c 1: - + 2 a y x + --- + 2 a c x + --- x b b . #+END_EXAMPLE Or undo that and integrate it, #+BEGIN_EXAMPLE 3 2 3 2 a y x a x y a c x a c x 2 1: x ln(x) - x + ------ + ------ + c x y + ------ + ------ + x c 3 2 b 3 2 b . #+END_EXAMPLE 太牛逼了! 一个文本编辑器居然可以做微积分! 目前为止, 我已经介绍了大多数的常用功能. 要想说完所有的功能太累人了,我只是讲了点皮毛而已. 很自然的, 我们也可以用elisp来扩展Calc. Calc还提供了一个宏 =defmath= 以方便我们进行扩展. 我希望有一天,Calc能够进行拉普拉斯和傅里叶变换.