EMACS-DOCUMENT

=============>集思广益

为程序员和计算机科学从业者所写的emacs-calc教程

1 Introduction

作为信息工程专业的研究生兼程序员,我常常需要计算内存地址,转换数据传输速率,进行二进制数与十六进制数的互转. 这些工作都可以由计算机来完成. 我是个Emacs nerd,但是我通常是使用duckduckgowolfram alpha 来进行这些计算的. 这些工具都挺不错的,但是过程比较繁琐,尤其是wlffram,有时候运行起来非常缓慢. 因此,我仔细研究了一下Emacs Calc以寻找在Emacs完成这些计算的方法.

1.1 Why Emacs?

我不明白为何会有此问. 我用Emacs编程,我用org-mode来记录我实验的进程和想法. 因此很自然的我会想用Emacs来完成这项任务. 此外,使用Emacs Calc有三大优势:

  1. Calc与Emacs本身一样,都是开源而可扩展的. 你无需等待下一个版本的发布. 若你足够的好奇,你可以完全搞明白Calc是怎么实现的. 而且,与Emacs其他mode一样,你可以以多种方式扩展Calc. 我将会在Units这章展示如何为Calc扩展更多的支持单位.
  2. Calc可以支持超复杂的计算. 它能够处理向量和矩阵,有理数,复数的计算. Karathik 将Calc比作穷人的mathematica.
  3. 若你对快捷键和RPN (逆波兰表示法) 熟悉的话,你的效率会很高. 研究表明 RPN在计算速度和精度上都要比代数表示法更好.

2 Numeral System

我在大学里学到的一个令人吃惊的真相是: 数值的值与它的表示是相分离的. 比如,数值5,可以被表示为5,V,five或101,但它的值总是不变的. 也就是说,数值5总是存在的,即使不存在一个系统来表示它. 然而,作为一名程序员和计算机科学家,你总要面对数值的不同表现形式,可能是二进制的,可能是十六进制的,也可能是八进程的. 那么,就让我们来看一下Calc在这方面能够做些什么吧.

2.1 Enter Numbers with different Base

若你在Calc输入一个数值,该数值会以当前基数的基数计数法显示(关于如何更改当前基,我会在下一章说明). 默认情况下,基数为10进制表示法(base 10). 若你想以不同基数表示的方式输入数值,你需要按格式 <number_of_base>#number 输入. 下面是一些例子:

Description Emacs Calc Base 10
Binary 2#11110101 245
Octal 8#27 23
Hexadecimal 16#FFFF 65535

很简单对不对! 然而,二进制数有两种表示方式:有符号整型和无符号整型. 让我们假设有w个bit,则其无符号整型的表示范围为0到2^w-1,而有符号整型的表示范围为-2^(w-1) 到 2^(w-1)-1. 后一种表示方法称为二进制补码. 默认情况下,Calc使用32个bit的字长来表示数值, 但你可以使用 b w (calc-word-size) 来改变字长. 你可以通过输入两次#的方式直接输入二进制补码,比如在字长为8的情况下输入 2##11110101 则其值为-11而不是245. 而且我前面也提过的,所有输入的数值都会被自动转换成以当前基数来表示.

2.2 Change Radix Mode

也就是说,你输入的数字和显示的数字是不一样的. 要修改显示数字的方式,你需要修改当前的基数,方法是按下 d r (calc-radix) 然后再输入基数(支持的范围为2-36). 当然,对于一些常见的基数,也有更快捷的快捷键进行修改:

 Shortcut 

这使得输入任意表达方式的数字都很方便,而且可以很方便的将之转换成其他基数的表示方式. 为了更好的比较以二进制形式表示的数字,可以按下 d z (calc-leading-zeros) 来在开启leading zero功能,该功能会在较短的数字前面补上0. 上面说的都是关于数字的表示方面的内容,下面让我们来看看如何操作这些二进制数.

3 Binary Number Operation

Calc提供了一个函数 b c (calc-clip) 来现符号/无符号整型的切换. This function clips the current number by reducing it by 2^w. 若字长为8bits,则你将是将符号整型转换为非符号整型,若字长为-8bits,则你是将非符号整型转换为符号整型. 下面是个例子:

emacs-calc-binary-clip.gif

字长的符号也会影响到下面二进制操作的结果:

输入 Calc函数 说明
b a (calc-and) Bitwise AND
b o (calc-or) Bitwise OR
b x (calc-xor) Bitwise XOR
b n (calc-not) Bitwise NOT
b d (calc-diff) Bitwise difference
b r (calc-rshift-binary) Bitwise right shift by 1 bit
b l (calc-lshift-binary) Bitwise left shift by 1 bit

你是否算过424242的二进制表达式中有多少个1呢? 没算过? 让我来告诉你怎样用Calc来得出答案吧. 先输入 424242 让它入栈,然后按下 b u 将该数字拆到集合中,然后按下 v # 算出1的个数,结果是10.

4 Units

Calc能够理解单位,并且预置了许多单位. 你可以按下 u v (calc-enter-units-table) 来看看Cacl预置了哪些单位. 要将带单位的数字入栈,需要输入 m a (calc-algebraic-entry) 然后再输入带单位的数字,例如 23m. 假设你想将单位转换为cm,只需要输入 u c (calc-convert-units) 然后再输入cm. 你甚至可以带单位进行计算. 你可以试试将23m和42cm累加起来. Calc会显示结果为 23 m + 42 cm, 若你再按下 u s (calc-simplify-units),结果显示为23.42m

但是很可惜,如果你仔细检查预定义的单位会发现并没有数字信息方面的单位. 但是不要紧,我们用的可是Emacs,我们可以按自己喜欢更改任何东西. Calc中有个教 math-additional-units 的变量可以用来添加新的单位. 该变量的格式必须准照 math-standard-units 那样. 下面这段Emacs Lisp代码能够为Calc添加数字信息单位:

(setq math-additional-units
      '((bit    nil           "Bit")
        (byte   "8 * bit"     "Byte")
        (bps    "bit / s"     "Bit per second"))
      math-units-table nil)

该代码片段还设置 math-units-table 为nil,以重建 the combined units table. 代码片段中无需定义以 (K)ilo, (M)ega or (G)iga开头的单位,因为Calc会自动处理这些前缀. 下面这个gif展示了如何使用这些单位:

emacs-calc-units-convert.gif

5 Conclusion

Emacs Calc十分强大,你可以使用 C-x * c 退出Calc. 这篇文章我只关注那些对程序员和计算机科学家可能有用的特性.它的manual也很不错, 推荐阅读.