逆波兰表示法

最初,bc程序基于一个叫dc(desk calculator,桌面计算器)的程序。dc是最古老的Unix
程序之一,甚至比C语言还要早。实际上,dc的最初版本是使用编程语言B(C的祖先)于

1970年编写的。一会之后,我们将进一步讨论bc和dc的关系。但是,现在我将讲授一些
有关dc的内容,dc本身就是一个十分有趣的程序,因为像bc—样,它是一个可以立即使
用的程序。
我们从一个技术描述开始:(dc是一个交互式、不定精确度的计算器,它仿真了一个使
用逆波兰表示法 Reverse Polish notation的栈机器。
很明显,dc并不是那种可以吸引所有人的程序类型:如果对数学或者计算机科学不感
兴趣,那么您可以自由地选择跳过该讨论。但是,如果您倾向于技术,那么对dc的理解
十分重要,原因有以下几方面。
首先,正如前面所述,dc使用了所谓的逆波兰表示法。尽管这一思想现在对您来说可
能没有任何意义,但是它是一个重要的概念,如果您将要学习数学、工程或者计算机科学,
那么应该重视这•概念。
其次,为了学习dc,您需要理解栈的思想(稍后解释),这是一个对计算机科学家和程
序员都很重要的概念。
最后,使用dc所需的思考方式与使用Unix所需的思考方式相同。因此,花一点时间
学习dc(如果乐意的话,可以自己学习如何使用它)将使您更进一步成为Unix人士。
我们将从逆波兰表示法的解释开始关于dc的讨论。在下一节中,将介绍栈的概念。
一旦理解了这两个基本思想,您就能够通过联机文档自学如何使用dc。
1920年,一位叫Jan Lukasiewicz (1878-1956)的波兰数学家观察我们书写算术表达式的
方式,发现可以通过将运算符放在操作数之前,使表达式更加紧凑。采用这种方式,我们
就能够不使用圆括号或者方括号书写复杂的表达式。下面示范一个简短的例子来描述这一
思想。
假设您希望将34加上25,然后把和乘以15。使用标准的表示法时,写法如下所示:
(34 + 25) *15
因为运算符(在这个例子中是+ (加号)和* (乘号))位于操作数的中间,所以我们称这种表
示法为中缀表示法 (infix notation)
Lukasiewicz的系统使用前綴表示法 (prefix notation),在这种表示法中,先书写运算符,
然后才是操作数。例如:
* + 34 25 15
为了求前缀表示法的值,我们从左向右,每次一个地处理元素。在这个例子中,首先
是*运算符,它告诉我们只要获得两个数字就执行一个乘法运算。然后我们遇到+运算符,
它告诉我们只要获得两个数字就执行一个加法运算。
接下来,连续获得两个数字34和25,因此我们执行加法运算,得到一个和59。记
.住这个59,我们继续,然后遇到了数字15。现在可以执行乘法59*15,获得最后结果
885。
为了纪念LukasiewiczD一名著名的数学家、逻辑学家和哲学家),通常将前缀表示法称

为波兰表示法(Polish notation),对于计算机科学家来说,波兰表示法十分重要,因为它紧
凑、直接,而且求值过程很高效。
1957年,奥地利计算机科学家Charles Hamblin撰写了两篇论文,在这两篇论文中,
他提议在基于栈的计算系统中使用波兰表示法的一种变体(我们将在下一节中讨论栈)。他
描述的变体就是将运算符放在操作数之后,这种表示法称为后缀表示法(postfix notation)。
为了描述后缀表示法,我们重新考虑前面的表达式。在后缀表示法中它如下所示:
34 25 + 15 *
为了求这种表达式的值,我们从左向右处理元素。首先,看到两个数字34和25,这
两个数字我们必须记住。接下来,我们看到+运算符,这告诉我们将之前两个可用的数字
加起来。在这个例子中,将34加上25得到59,这个数字我们也必须记住。
接下来,我们看到数字15,这个数字也要记住。最后,看到*运算符,它告诉我们将最
后两个数字乘在一起。在这个例子中,两个数字是59和15,将它们乘起来获得最后结果885。
后缀表示法特别适合自动计算,这是因为表达式可以通过记住数字并应用遇到的运算
符,以一种直接的方式从左向右求值。对于中缀表示法,括号和其他类型的优先级(例如乘
法必须先于加法完成)通常要求某些运算必须一直等到其他运算完成时才能进行。而后缀表
示法就没有这种问题。
为了纪念Lukasiewicz,后缀表示法通常称为逆波兰表示法或者简称为RPN。多年以
来,波兰表示法和逆波兰表示法在许多计算机系统中都得到广泛的应用。例如,Lisp编程
语言和Tel脚本语言中就使用了波兰(前缀)表示法。Forth编程语言和PostScript页面描述语
言就使用了逆波兰(后缀)表示法。
或许RPN最有名的应用就是作为HP计算器的基础。HP计算器己被广大科学家和工
程师使用了许多年。第、个此类计算器是HP9100,于1968年发明。
从那时起,RPN计算器就幵始流行,因为一旦您理解了 RPN,相对于传统的中缀表示
法,它要快许多,并且使用更容易。例如,当您使用RPN计算器时,每个计算的结果会立
即显示。这意味着在输入运算时可以看到局部结果,从而使错误的捕捉相对容易。而使用
传统中缀表示法的计算器,情况就不是这样了。如果您输入了一个使用标准优先级规则的
表达式,那么除非整个运算结束,否则结果是不会显示出来的。
1970年,贝尔实验室的一名研究人员Robert Morris,受HP计算器的启发,使用RPN
开发了 -个基于Unix的交互式计算器程序。Morris将这个程序称为dc(desk calculator,桌
面计算器)。dc是一个神奇的工具,但是它要求用户学习如何使用RPN。
几年之后,Morris和另一名研究人员Lorinda Cherry 一起编写了另一个名叫bc的程序,
该程序允许用户使用更传统的中缀表示法书写算式。bc的工作方式是将输入转换成RPN,
然后调用dc完成实际工作。换句话说,be是de的“前端”。这允许人们选择他们喜爱的
系统:dc的后缀表示法或者bc的中缀表示法。

若干年之后,作为GNU项目(参见第2章)的一部分,bc作为一个独立的程序完全
进行了重写。因为许多现代的Unix(包括Linux和FreeBSD)都使用GNU实用工具,所
以当您现在使用bc时,使用的是一个不再依赖于dc的独立程序。当然,dc仍然可以
单独使用。

posted @ 2021-11-15 14:32  HFF0131  阅读(68)  评论(1)    收藏  举报