逆波兰

波兰(Poland)是个了不起的国家。元素周期表中的放射性元素钋(Po),是居里夫人发现的,是以她的祖国波兰命名的。在计算机科学中常用到的波兰表达式(Polish Notation)、逆波兰表达式(Reverse Polish Notation)也是以波兰命名的。中国也是个了不起的国家,我知道的中国剩余定理(Chinese remainder theorem)是以中国冠名的。其他以中国冠名的物件有中国结、中国龙(Chinese Dragon)、中国梦、中国模式、中国特色的社会主义等。嗯,今天不说中国,主要说波兰。

波兰逻辑学家扬·武卡谢维奇(Jan Lukasiewicz)在1924年发明了波兰表达式,用于简化命题逻辑,后来波兰表达式也用于算数(Arighmatic)和代数(Algebra)。通常的表达式叫中缀表达式,这种表达式运算符(operator)在操作数(operand)的中间。例如表达式1 + 2的运算符+位于操作数1和2的中间。波兰表达式也叫前缀表达式,这种表达式运算符在操作数的前面。中缀表达式1 + 2对应的前缀表达式是+ 1 2。

好好的中缀表达式不用,用什么前缀表达式?

运算符是有优先级的。例如中缀表达式1+2×3要先算乘法后算加法。如果我们要先算加法后算乘法,那通常我们需要加括号改变运算顺序。例如(1+2)×3。而如果用前缀表达式,在运算符的参数个数(arity)已知的情况下,我们可以省略括号。例如前缀表达式×+ 1 2 3对应中缀表达式为(1+2)×3。前缀表达式在Lisp计算机语言中有广泛的应用。

逆波兰表达式是计算机科学家F. L. Bauer和E. W. Dijkstra在20世纪60年代各自独立发明的。逆波兰表达式也叫后缀表达式,这种表达式运算符在操作数的后面。中缀表达式1 + 2对应的后缀表达式是1 2 +。不太严格地说,后缀表达式基本上是前缀表达式反过来。后缀表达式具有前缀表达式的好处,即不需要括号来改变运算顺序。另外的好处就是很容易用一个栈(Last In First Out)的数据结构实现从左到右一次扫描来计算表达式的值。(如果前缀表达式,要从右往左扫描,不顺手吧)后缀表达式在Forth、PostScript等计算机语言中有广泛的应用。

下面是采用栈计算后缀表达式3 2 + 4 -的步骤(对应中缀表达式为3 + 2 - 4),左边是栈底,右边是栈顶。

3
3 2
3 2 +
5
5 4
5 4 -
1

同时我觉得后缀表达式可能比较适合用来实现中文编程。英文句子的单词都用空格分开,英文中的符号很丰富,圆括号、方括号、花括号等应有尽有,所以英文编程语言使用这些符号很自然。而中文中这些符号都是后来加的,古文中甚至句逗都没有。所以我觉得自然的中文编程语言应该越少使用符号越好。另外中文中的倒装用法本来也很多,倒装和逆波兰表达式有神似之处。比如中文的“吾谁与归”指“吾与谁归”,“走你”指“你走”等。

下面是使用处于试验阶段的微型亲密数编程语言采用后缀表达式来计算3 + 2 - 4的过程。“和”用来分开数字。“加”和“减”是+和-运算符。每个步骤输出的结果都保存在栈中。

欢迎试用亲密数语言!
亲> 三和二
三和二
亲> 加
五
亲> 和四
五和四
亲> 减
一
亲> 

这里要说一下,逆波兰表达式的发明者F. L. Bauer是德国人,E. W. Dijkstra是荷兰人,他们的发明和波兰表达式相反,叫逆波兰表达式,没有叫德国或荷兰表达式。波兰表达式的发明者扬·武卡谢维奇发明了一个实际赚到了俩。我爷爷愿意供子女读书,他的理论是穷要读书(现在丑也要读书),富要养猪。他还有个理论是,供出一个大学生相当于供出俩。因为供出一个大学生还会再娶(嫁)一个大学生。这当然是基于他老人家对就业和找对象都比较乐观的前提得出的结论。

参考资料

[1] http://en.wikipedia.org/wiki/Polish_notation

[2] http://en.wikipedia.org/wiki/Reverse_Polish_notation

时间: 2024-10-12 03:28:14

逆波兰的相关文章

LeetCode之逆波兰式求解

计算逆波兰式子: 有效的操作只有 +, -, *, /. 每一个输入不是一个整数就是一个操作符. Some examples: ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9 ["4", "13", "5", "/", "+"] -> (4 +

HDU1237 简单计算器 【栈】+【逆波兰式】

版本:1.0 日期:2014.5.17 2014.6.1 版权:© 2014 kince 转载注明出处 在介绍SwitchButton之前,先来看一下系统Button是如何实现的.源码如下: @RemoteView public class Button extends TextView { public Button(Context context) { this(context, null); } public Button(Context context, AttributeSet att

逆波兰表达式

1696:逆波兰表达式 总时间限制: 1000ms 内存限制: 65536kB 描述 逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* + 2 3 4.本题求解逆波兰表达式的值,其中运算符包括+ - * /四个. 输入 输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数. 输出 输出为一行,表达式的值.可直接用prin

中缀输入逆波兰计算器程序part1

在看K&R的时候,里面提到了逆波兰表示法,老实说看得我迷迷糊糊的,主要是这种反人类的后缀表示法做出的计算器,一般人根本就不知道怎么输入好吧.今天看书的时候,看到了将中缀表达式转为后缀表达式的方法才恍然大悟,原来是少了这一步.这下我就知道该如何做一个可用的逆波兰计算器了. 先简单介绍一下如何完成这步转换吧.中缀表达式就是我们习惯的表达式,比如:1+2*3 考虑运算符优先级的话后缀表达式则应该写成123*+ 写成后缀表达式的形式后我们可以利用栈轻松地解决计算问题,思路是当见到一个数时就把它推入栈:在

lintcode 中等题:Evaluate Reverse Polish notation逆波兰表达式求值

题目 逆波兰表达式求值 在逆波兰表达法中,其有效的运算符号包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰计数表达. 样例 ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9 ["4", "13", "5", "/", "+"]

使用逆波兰式进行表达式求值

中缀表达式及后缀表达式图解中说明了使用逆波兰式进行表达式求值的方法,这里使用C++进行实现.实现和原理讲解有一点不同,需要进一步进行细化. 关于将中缀表达式转换成后后缀表达式的规则: 规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分:若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止. 上面的规则转换成下面的执行规则: 1.遇到操作数:直接输出(添加到后缀

逆波兰式与表达式求解

/*************** 逆波兰式即后缀表示法 预处理 ---- 中序表达式->逆序表达式(infix to postfix) 算法: while(表达式非空) if (遇到操作数) 直接输出 else if (遇到操作符op) op是( 直接入栈s op是) s.push输出,直到( op是四则运算,则 if (s为空 || s.top为( || op 优先级高于 s.top) op 入栈 else s.push输出 if (!s.empty) s.push输出 计算 算法: if (

求解逆波兰表达式的值

题目: Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, *, /. Each operand may be an integer or another expression. Some examples:   ["2", "1", "+", "3", "*"

[Leetcode] evaluate reverse polish notation 计算逆波兰表达式

Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are+,-,*,/. Each operand may be an integer or another expression. Some examples: ["2", "1", "+", "3", "*"] -> (

栈的操作实现逆波兰表达式的计算

代码如下: #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define STACK_INIT_SIZE 20 #define STACKINCREMENT 10 #define MAXBUFFER 10 typedef double ElemType; typedef struct { ElemType *base; ElemType *top; int StackSize; }sqStack; v