逆波兰表示法:修订间差异
Pittigrilli(留言 | 贡献) I added video showing use of RPN on an HP-32SII calculator. The caption text was translated using Google - if there should be errors, please correct them. 标签:添加文件 |
|||
(未显示25个用户的45个中间版本) | |||
第1行: | 第1行: | ||
{{NoteTA|G1=Math|G2=IT}} |
|||
{{Infobox notation|logo=[[File:Postfix-dia.svg|125px]]}} |
{{Infobox notation|logo=[[File:Postfix-dia.svg|125px]]}} |
||
[[File:Typing the calculation for "8 times 6" into a pocket calculator HP-32SII which uses RPN logic.webm|thumb|upright|影片:在 1991 年 [[Hewlett-Packard]] HP-32SII 上鍵入按鍵序列來計算八乘六]] |
|||
'''逆波兰表示法'''({{lang|en|'''Reverse Polish notation'''}},{{lang|en|'''RPN'''}},或'''逆波兰记法'''),是一种是由[[波兰]][[数学家]][[扬·武卡谢维奇]]1920年引入的数学表达式方式,在逆波兰记法中,所有[[操作符]]置于[[操作数]]的后面,因此也被称为'''后缀表示法'''。逆波兰记法不需要括号来标识操作符的优先级。 |
|||
'''逆波兰表示法'''({{lang-en|Reverse Polish notation}},縮寫'''RPN''',或'''逆波兰记法'''、'''逆卢卡西维茨记法'''),是一种由[[波兰]]数学家[[扬·卢卡西维茨]]于1920年引入的数学[[表达式]]形式,在逆波兰记法中,所有[[運算子|操作符]]置于[[操作数]]的后面,因此也被称为'''后缀表示法'''、'''後序表示法'''<ref>{{Cite web |title=課程名稱:程式設計 - 中序轉後序、前序 |url=https://sites.google.com/qtm.ks.edu.tw/qtmcoding/c%E8%AA%9E%E8%A8%80/%E4%B8%AD%E5%BA%8F%E8%BD%89%E5%BE%8C%E5%BA%8F%E5%89%8D%E5%BA%8F |website=sites.google.com |language=zh-CN |access-date=2022-08-22 |archive-date=2022-08-22 |archive-url=https://web.archive.org/web/20220822064526/https://sites.google.com/qtm.ks.edu.tw/qtmcoding/c%E8%AA%9E%E8%A8%80/%E4%B8%AD%E5%BA%8F%E8%BD%89%E5%BE%8C%E5%BA%8F%E5%89%8D%E5%BA%8F |dead-url=no }}</ref>。逆波兰记法不需要括号来标识操作符的优先级。 |
|||
逆波兰结构由 |
逆波兰结构由{{le|弗里德里希·L·鲍尔|Friedrich L. Bauer}}和[[艾兹格·迪科斯彻]]在1960年代早期提议用于表达式求值,以利用[[堆栈|堆栈结构]]减少计算机[[内存]]访问。逆波兰记法和相应的[[算法]]由[[澳大利亚]]哲学家、计算机学家{{le|查尔斯·伦纳德·汉布林|Charles Leonard Hamblin}}在1960年代中期扩充<ref>[http://www.csc.liv.ac.uk/~peter/hamblin.html "Charles L. Hamblin and his work"] {{webarchive|url=https://web.archive.org/web/20081206093044/http://www.csc.liv.ac.uk/~peter/hamblin.html |date=2008-12-06 }} by Peter McBurney</ref><ref>[http://www.csc.liv.ac.uk/~peter/this-month/this-month-3-030303.html "Charles L. Hamblin: Computer Pioneer"] {{webarchive|url=https://web.archive.org/web/20081207005233/http://www.csc.liv.ac.uk/~peter/this-month/this-month-3-030303.html |date=2008-12-07 }} by Peter McBurney, July 27, 2008. "''Hamblin soon became aware of the problems of (a) computing mathematical formulae containing brackets, and (b) the memory overhead in having dealing with memory stores each of which had its own name. One solution to the first problem was Jan Lukasiewicz's Polish notation, which enables a writer of mathematical notation to instruct a reader the order in which to execute the operations (e.g. addition, multiplication, etc) without using brackets. Polish notation achieves this by having an operator (+, *, etc) precede the operands to which it applies, e.g., +ab, instead of the usual, a+b. Hamblin, with his training in formal logic, knew of Lukasiewicz's work.''" </ref>。 |
||
在1960和1970年代,逆波兰记法广泛地被用于台式[[计算器]],因此也在普通公众([[工程]]、[[商业]]和[[金融]]领域)中使用。 |
在1960和1970年代,逆波兰记法广泛地被用于台式[[计算器]],因此也在普通公众(如[[工程]]、[[商业]]和[[金融]]等领域)中使用。 |
||
下面大部分是关于[[二元运算]],一个[[一元运算]]使用逆波兰记法的例子是[[阶乘]]的记法。 |
下面大部分是关于[[二元运算]],一个[[一元运算]]使用逆波兰记法的例子是[[阶乘]]的记法。 |
||
== 解释 == |
== 解释 == |
||
逆波兰记法中,操作符置于操作数的后面。例如表达“三加四”时,写作 |
逆波兰记法中,操作符置于操作数的后面。例如表达“三加四”时,写作“{{波兰表示法|逆|3+4}}”,而不是“3 + 4”。如果有多个操作符,操作符置于第二个操作数的后面,所以常规中缀记法的“3 - 4 + 5”在逆波兰记法中写作“{{波兰表示法|逆|3 - 4 + 5}}”:先3减去4,再加上5。使用逆波兰记法的一个好处是不需要使用括号。例如中缀记法中“3 - 4 * 5”与“(3 - 4)*5”不相同,但后缀记法中前者写做“{{波兰表示法|逆|3 - 4 * 5}}”,无歧义地表示“3 (4 5 *) -”;后者写做“{{波兰表示法|逆|(3 - 4)*5}}”。 |
||
逆波兰表达式的[[解释器]]一般是基于[[堆栈]]的。解释过程一般是:操作数入栈;遇到操作符时,操作数出栈,求值,将结果入栈;当一遍后,栈顶就是表达式的值。因此逆波兰表达式的求值使用堆栈结构很容易实现, |
逆波兰表达式的[[解释器]]一般是基于[[堆栈]]的。解释过程一般是:操作数入栈;遇到操作符时,操作数出栈,求值,将结果入栈;当一遍后,栈顶就是表达式的值。因此逆波兰表达式的求值使用堆栈结构很容易实现,并且能很快求值。 |
||
注意:逆波兰记法并不是简单的[[波兰表达式]]的反转。因为对于不满足[[交换律]]的操作符,它的操作数写法仍然是常规顺序,如,波兰记法“/ 6 3”的逆波兰记法是“6 3 /”而不是“3 6 /”;数字的数位写法也是常规顺序。 |
注意:逆波兰记法并不是简单的[[波兰表达式]]的反转。因为对于不满足[[交换律]]的操作符,它的操作数写法仍然是常规顺序,如,波兰记法“/ 6 3”的逆波兰记法是“6 3 /”而不是“3 6 /”;数字的数位写法也是常规顺序。 |
||
第23行: | 第25行: | ||
=== 伪代码 === |
=== 伪代码 === |
||
* while有输入 |
* while 有输入 |
||
** 读入下一个符号 |
** 读入下一个符号X |
||
** IF是一个操作数 |
** IF X是一个操作数 |
||
*** 入栈 |
*** 入栈 |
||
** ELSE IF是一个操作符 |
** ELSE IF X是一个操作符 |
||
*** 有一个先验的表格给出该操作符需要n个参数 |
*** 有一个先验的表格给出该操作符需要n个参数 |
||
*** IF堆栈中少于n个操作数 |
*** IF堆栈中少于n个操作数 |
||
第40行: | 第42行: | ||
=== 例子 === |
=== 例子 === |
||
中缀表达式“5 + ((1 + 2) * 4) |
中缀表达式“5 + ((1 + 2) * 4) - 3”写作 |
||
: 5 1 |
: {{波兰表示法|逆|5 + ((1 + 2) * 4) - 3}} |
||
下表给出了该逆波兰表达式从左至右求值的过程,堆栈栏给出了中间值,用于跟踪算法。 |
下表给出了该逆波兰表达式从左至右求值的过程,堆栈栏给出了中间值,用于跟踪算法。 |
||
{|class="wikitable" |
{|class="wikitable" |
||
! 输入 |
! 输入 !! 操作 !! 堆栈 !! 注释 |
||
|- |
|- |
||
| 5 || 入栈 |
| 5 || 入栈 || 5 || |
||
|- |
|- |
||
| 1 || 入栈 |
| 1 || 入栈 || 5, 1 || |
||
|- |
|- |
||
| 2 || 入栈 |
| 2 || 入栈 || 5, 1, 2 || |
||
|- |
|- |
||
| |
| + || 加法运算 || 5, 3 || 1, 2出栈,将结果3入栈 |
||
|- |
|- |
||
| 4 || 入栈 |
| 4 || 入栈 || 5, 3, 4 || |
||
|- |
|- |
||
| * || 乘法运算 |
| * || 乘法运算 || 5, 12 || 3, 4出栈,将结果12入栈 |
||
|- |
|- |
||
| |
| + || 加法运算 || 17 || 5, 12出栈,将结果17入栈 |
||
|- |
|- |
||
| 3 || 入栈 |
| 3 || 入栈 || 17, 3 || |
||
|- |
|||
⚫ | |||
|- |
|- |
||
⚫ | |||
|} |
|} |
||
计算完成时,栈内只有一个操作数,这就是表达式的结果:14 |
计算完成时,栈内只有一个操作数,这就是表达式的结果:14 |
||
==C++程序实现== |
|||
<syntaxhighlight lang="cpp"> |
|||
#include <iostream> |
|||
#include<queue> |
|||
#include<stack> |
|||
#define ERROR 0 |
|||
#define OK 1 |
|||
using namespace std; |
|||
typedef int Staus; |
|||
typedef double ElemType; |
|||
bool Get_ops(stack<ElemType>* st, ElemType* op1, ElemType* op2) |
|||
{ |
|||
if (st->size() < 2) |
|||
return ERROR; |
|||
*op1 = st->top(); |
|||
st->pop(); |
|||
*op2 = st->top(); |
|||
st->pop(); |
|||
return OK; |
|||
} |
|||
Staus Solve(stack<ElemType>* st, char oper) |
|||
{ |
|||
bool flag = 0; |
|||
ElemType oper1, oper2; |
|||
flag = Get_ops(st, &oper1, &oper2); |
|||
if (flag) |
|||
{ |
|||
switch (oper) |
|||
{ |
|||
case('+'):st->push(oper2 + oper1); break; |
|||
case('-'):st->push(oper2 - oper1); break; |
|||
case('*'):st->push(oper2 * oper1); break; |
|||
case('/'):if (!oper1) |
|||
{ |
|||
cout << "Divide by 0!" << endl; |
|||
return ERROR; |
|||
} |
|||
else st->push(oper2 / oper1); |
|||
break; |
|||
case('^'):st->push(pow(oper2, oper1)); break; |
|||
} |
|||
} |
|||
else return ERROR; |
|||
return OK; |
|||
} |
|||
int main() |
|||
{ |
|||
stack<ElemType> suffix; |
|||
char c; |
|||
ElemType t; |
|||
c = getchar(); |
|||
while (c != '#') |
|||
{ |
|||
switch (c) |
|||
{ |
|||
case(' '):break; |
|||
case('+'):; |
|||
case('-'):; |
|||
case('*'):; |
|||
case('/'):; |
|||
case('^'):Solve(&suffix, c); break; |
|||
default:ungetc(c, stdin); |
|||
cin >> t; |
|||
suffix.push(t); |
|||
} |
|||
c = getchar(); |
|||
} |
|||
cout << suffix.top() << endl; |
|||
return 0; |
|||
} |
|||
</syntaxhighlight> |
|||
上述运算可以重写为如下运算链方法(用于HP的逆波兰计算器):<ref> |
上述运算可以重写为如下运算链方法(用于HP的逆波兰计算器):<ref>"As was demonstrated in the Algebraic mode, it is usually easier (fewer keystrokes) in working a problem like this to begin with the arithmetic operations inside the parentheses first."[http://h20219.www2.hp.com/Hpsub/downloads/17b2pChain.pdf] {{Wayback|url=http://h20219.www2.hp.com/Hpsub/downloads/17b2pChain.pdf |date=20110712224633 }}</ref> |
||
⚫ | |||
"As was demonstrated in the Algebraic mode, it is usually easier (fewer keystrokes) in working a problem like this to begin with the arithmetic operations inside the parentheses first."[http://h20219.www2.hp.com/Hpsub/downloads/17b2pChain.pdf] </ref> |
|||
⚫ | |||
== 实现 == |
== 实现 == |
||
第86行: | 第165行: | ||
* 任何基于栈的程序语言: |
* 任何基于栈的程序语言: |
||
** [[Forth]] |
** [[Forth]] |
||
** [[Factor语言]] |
** [[Factor (编程语言)|Factor]] |
||
** [[PostScript]]语言。 |
** [[PostScript]]语言。 |
||
* 线上的[http://www.rpn-calculator.com/ 逆波兰计算器] |
* 线上的[https://web.archive.org/web/20120110034031/http://www.rpn-calculator.com/ 逆波兰计算器] |
||
* Windows下[http://www.farsightsoft.com 逆波兰计算器] |
* Windows下[https://web.archive.org/web/20181003181815/http://www.farsightsoft.com/ 逆波兰计算器] |
||
* Windows XP下的[http://www.microsoft.com/windowsxp/downloads/powertoys/xppowertoys.mspx Microsoft PowerToy calculator] |
* Windows XP下的[http://www.microsoft.com/windowsxp/downloads/powertoys/xppowertoys.mspx Microsoft PowerToy calculator] {{Wayback|url=http://www.microsoft.com/windowsxp/downloads/powertoys/xppowertoys.mspx |date=20100424025907 }} |
||
* [http://midp-calc.sourceforge.net 手机逆波兰计算器]开源的[[JAVA]]计算器 |
* [http://midp-calc.sourceforge.net 手机逆波兰计算器] {{Wayback|url=http://midp-calc.sourceforge.net/ |date=20050409112936 }}开源的[[JAVA]]计算器 |
||
* [[Palm PDA]]下的[http://www.nthlab.com/software/rpn 逆波兰计算器] |
* [[Palm PDA]]下的[http://www.nthlab.com/software/rpn 逆波兰计算器] {{Wayback|url=http://www.nthlab.com/software/rpn |date=20210311233934 }} |
||
* [[Calculator (Mac OS X)|Mac OS X计算器]] |
* [[Calculator (Mac OS X)|Mac OS X计算器]] |
||
* [[Mac OS X]]和[[iPhone]]下的[http://www.pcalc.com 逆波兰计算器] |
* [[Mac OS X]]和[[iPhone]]下的[http://www.pcalc.com 逆波兰计算器] {{Wayback|url=http://www.pcalc.com/ |date=20210501155527 }} |
||
* [[Unix]]下的计算程序[[Dc ( |
* [[Unix]]下的计算程序[[Dc (程序)|dc]] |
||
* 交互式[[JavaScript]]的逆波兰计算器:[http://main.linuxfocus.org/~guido/javascript/rpnjcalc.html ]和[http://dse.webonastick.com/rpncalc/ ] |
* 交互式[[JavaScript]]的逆波兰计算器:[http://main.linuxfocus.org/~guido/javascript/rpnjcalc.html ] {{Wayback|url=http://main.linuxfocus.org/~guido/javascript/rpnjcalc.html |date=20201010145341 }}和[https://web.archive.org/web/20061205221559/http://dse.webonastick.com/rpncalc/ ] |
||
* [[Wikibooks:Ada Programming/Mathematical calculations]] <small>([[Ada]]语言中的逆波兰计算器)</small> |
* [[Wikibooks:Ada Programming/Mathematical calculations]] <small>([[Ada]]语言中的逆波兰计算器)</small> |
||
* [[Emacs]]的lisp lib包: calc |
* [[Emacs]]的lisp lib包: calc |
||
* 基于[[GTK+]]的[http://galculator.sourceforge.net/ galculator] |
* 基于[[GTK+]]的[http://galculator.sourceforge.net/ galculator] {{Wayback|url=http://galculator.sourceforge.net/ |date=20150802151441 }} |
||
* 表达式转换[http://www.java2s.com/Code/JavaScript/Development/Postfix-Infix.htm] |
* 表达式转换[http://www.java2s.com/Code/JavaScript/Development/Postfix-Infix.htm] {{Wayback|url=http://www.java2s.com/Code/JavaScript/Development/Postfix-Infix.htm |date=20210108014425 }} |
||
* scratch |
|||
== 注释 == |
== 注释 == |
||
第108行: | 第188行: | ||
* [[Forth]] |
* [[Forth]] |
||
* [[PostScript]] |
* [[PostScript]] |
||
* |
* {{le|HP计算器|HP calculators}} |
||
* [[LIFO]] |
* [[LIFO]] |
||
* [[栈机器]](Stack machine) |
* [[栈机器]](Stack machine) |
||
* [[波兰表示法]] |
* [[波兰表示法]] |
||
* [[面向堆栈编程]] |
|||
== 参考 == |
== 参考 == |
||
* [http://www.xnumber.com/xnumber/rpn_or_adl.htm ''RPN or DAL? A brief analysis of Reverse Polish Notation against Direct Algebraic Logic''] – By James Redin |
* [http://www.xnumber.com/xnumber/rpn_or_adl.htm ''RPN or DAL? A brief analysis of Reverse Polish Notation against Direct Algebraic Logic''] {{Wayback|url=http://www.xnumber.com/xnumber/rpn_or_adl.htm |date=20170624164945 }} – By James Redin |
||
* [http://www.spsu.edu/cs/faculty/bbrown/web_lectures/postfix/ Postfix Notation Mini-Lecture] – By Bob Brown |
* [http://www.spsu.edu/cs/faculty/bbrown/web_lectures/postfix/ Postfix Notation Mini-Lecture] {{Wayback|url=http://www.spsu.edu/cs/faculty/bbrown/web_lectures/postfix/ |date=20110806101729 }} – By Bob Brown |
||
* [http://www.langmaker.com/shallowfith.htm Fith: An Alien Conlang With A LIFO Grammar] – By Jeffrey Henning |
* [https://web.archive.org/web/20090322143156/http://www.langmaker.com/shallowfith.htm Fith: An Alien Conlang With A LIFO Grammar] – By Jeffrey Henning |
||
* [http://www.cs.inf.ethz.ch/~wirth/Articles/GoodIdeas_origFig.pdf Good Ideas, Through the Looking Glass] - By Nick Wurth |
* [https://web.archive.org/web/20100331222736/http://www.cs.inf.ethz.ch/~wirth/Articles/GoodIdeas_origFig.pdf Good Ideas, Through the Looking Glass] - By Nick Wurth |
||
[[Category:数学表示法]] |
[[Category:数学表示法]] |
||
[[Category:波兰科技]] |
|||
[[Category:运算符_(编程)]] |
2024年6月4日 (二) 15:16的最新版本
前缀表示法 (+ 3 4 ) |
中缀表示法 (3 + 4) |
后缀表示法 (3 4 + ) |
逆波兰表示法(英語:Reverse Polish notation,縮寫RPN,或逆波兰记法、逆卢卡西维茨记法),是一种由波兰数学家扬·卢卡西维茨于1920年引入的数学表达式形式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法、後序表示法[1]。逆波兰记法不需要括号来标识操作符的优先级。
逆波兰结构由弗里德里希·L·鲍尔和艾兹格·迪科斯彻在1960年代早期提议用于表达式求值,以利用堆栈结构减少计算机内存访问。逆波兰记法和相应的算法由澳大利亚哲学家、计算机学家查尔斯·伦纳德·汉布林在1960年代中期扩充[2][3]。
在1960和1970年代,逆波兰记法广泛地被用于台式计算器,因此也在普通公众(如工程、商业和金融等领域)中使用。
下面大部分是关于二元运算,一个一元运算使用逆波兰记法的例子是阶乘的记法。
解释
[编辑]逆波兰记法中,操作符置于操作数的后面。例如表达“三加四”时,写作“3 4 + ”,而不是“3 + 4”。如果有多个操作符,操作符置于第二个操作数的后面,所以常规中缀记法的“3 - 4 + 5”在逆波兰记法中写作“3 4 - 5 + ”:先3减去4,再加上5。使用逆波兰记法的一个好处是不需要使用括号。例如中缀记法中“3 - 4 * 5”与“(3 - 4)*5”不相同,但后缀记法中前者写做“3 4 5 * - ”,无歧义地表示“3 (4 5 *) -”;后者写做“3 4 - 5 * ”。
逆波兰表达式的解释器一般是基于堆栈的。解释过程一般是:操作数入栈;遇到操作符时,操作数出栈,求值,将结果入栈;当一遍后,栈顶就是表达式的值。因此逆波兰表达式的求值使用堆栈结构很容易实现,并且能很快求值。
注意:逆波兰记法并不是简单的波兰表达式的反转。因为对于不满足交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法“/ 6 3”的逆波兰记法是“6 3 /”而不是“3 6 /”;数字的数位写法也是常规顺序。
与中缀记法的转换
[编辑]艾兹格·迪科斯彻引入了调度场算法,用于将中缀表达式转换为后缀形式。因其操作类似于火车編組場而得名。 大多数操作符优先级解析器(解析器用简单的查表操作即可实现,优先级表由开发者自己定制,在不同的应用场景中,开发者可自由改变操作符的优先级)能转换为处理后缀表达式,实际中,一般构造抽象语法树,树的后序遍历即为逆波兰记法。
逆波兰表达式求值
[编辑]伪代码
[编辑]- while 有输入
- 读入下一个符号X
- IF X是一个操作数
- 入栈
- ELSE IF X是一个操作符
- 有一个先验的表格给出该操作符需要n个参数
- IF堆栈中少于n个操作数
- (错误) 用户没有输入足够的操作数
- Else,n个操作数出栈
- 计算操作符。
- 将计算所得的值入栈
- IF栈内只有一个值
- 这个值就是整个计算式的结果
- ELSE多于一个值
- (错误) 用户输入了多余的操作数
例子
[编辑]中缀表达式“5 + ((1 + 2) * 4) - 3”写作
- 5 1 2 + 4 * + 3 -
下表给出了该逆波兰表达式从左至右求值的过程,堆栈栏给出了中间值,用于跟踪算法。
输入 | 操作 | 堆栈 | 注释 |
---|---|---|---|
5 | 入栈 | 5 | |
1 | 入栈 | 5, 1 | |
2 | 入栈 | 5, 1, 2 | |
+ | 加法运算 | 5, 3 | 1, 2出栈,将结果3入栈 |
4 | 入栈 | 5, 3, 4 | |
* | 乘法运算 | 5, 12 | 3, 4出栈,将结果12入栈 |
+ | 加法运算 | 17 | 5, 12出栈,将结果17入栈 |
3 | 入栈 | 17, 3 | |
- | 减法运算 | 14 | 17, 3出栈,将结果14入栈 |
计算完成时,栈内只有一个操作数,这就是表达式的结果:14
C++程序实现
[编辑]#include <iostream>
#include<queue>
#include<stack>
#define ERROR 0
#define OK 1
using namespace std;
typedef int Staus;
typedef double ElemType;
bool Get_ops(stack<ElemType>* st, ElemType* op1, ElemType* op2)
{
if (st->size() < 2)
return ERROR;
*op1 = st->top();
st->pop();
*op2 = st->top();
st->pop();
return OK;
}
Staus Solve(stack<ElemType>* st, char oper)
{
bool flag = 0;
ElemType oper1, oper2;
flag = Get_ops(st, &oper1, &oper2);
if (flag)
{
switch (oper)
{
case('+'):st->push(oper2 + oper1); break;
case('-'):st->push(oper2 - oper1); break;
case('*'):st->push(oper2 * oper1); break;
case('/'):if (!oper1)
{
cout << "Divide by 0!" << endl;
return ERROR;
}
else st->push(oper2 / oper1);
break;
case('^'):st->push(pow(oper2, oper1)); break;
}
}
else return ERROR;
return OK;
}
int main()
{
stack<ElemType> suffix;
char c;
ElemType t;
c = getchar();
while (c != '#')
{
switch (c)
{
case(' '):break;
case('+'):;
case('-'):;
case('*'):;
case('/'):;
case('^'):Solve(&suffix, c); break;
default:ungetc(c, stdin);
cin >> t;
suffix.push(t);
}
c = getchar();
}
cout << suffix.top() << endl;
return 0;
}
上述运算可以重写为如下运算链方法(用于HP的逆波兰计算器):[4]
- 1 2 + 4 * 5 + 3 -
实现
[编辑]第一代实现了逆波兰架构的电子计算机是英国电气公司1963年交付使用的KDF9和美国的Burroughs B5000。Friden公司在它1963年推出的EC-130中,将逆波兰表达式引入了台式计算器市场。惠普1968年设计了9100A逆波兰计算器,首台手持式计算器HP-35也使用逆波兰表达式,惠普在HP-10A之前的所有手持计算器(包括科学计算,金融和可编程)中使用了逆波兰表达式,并在1980年代晚期的LCD显示计算器如HP-10C, HP-11C, HP-15C, HP-16C,等都是用了逆波兰表达式。
实际意义
[编辑]- 当有操作符时就计算,因此,表达式并不是从右至左整体计算而是每次由中心向外计算一部分,这样在复杂运算中就很少导致操作符错误。
- 堆栈自动记录中间结果,这就是为什么逆波兰计算器能容易对任意复杂的表达式求值。与普通科学计算器不同,它对表达式的复杂性没有限制。
- 逆波兰表达式中不需要括号,用户只需按照表达式顺序求值,让堆栈自动记录中间结果;同样的,也不需要指定操作符的优先级。
- 逆波兰计算器中,没有“等号”键用于开始计算。
- 逆波兰计算器需要“确认”键用于区分两个相邻的操作数。
- 机器状态永远是一个堆栈状态,堆栈里是需要运算的操作数,栈内不会有操作符。
- 教育意义上,逆波兰计算器的使用者必须懂得要计算的表达式的含义。
目前逆波兰的实现有:
- 任何基于栈的程序语言:
- 线上的逆波兰计算器
- Windows下逆波兰计算器
- Windows XP下的Microsoft PowerToy calculator (页面存档备份,存于互联网档案馆)
- 手机逆波兰计算器 (页面存档备份,存于互联网档案馆)开源的JAVA计算器
- Palm PDA下的逆波兰计算器 (页面存档备份,存于互联网档案馆)
- Mac OS X计算器
- Mac OS X和iPhone下的逆波兰计算器 (页面存档备份,存于互联网档案馆)
- Unix下的计算程序dc
- 交互式JavaScript的逆波兰计算器:[2] (页面存档备份,存于互联网档案馆)和[3]
- Wikibooks:Ada Programming/Mathematical calculations (Ada语言中的逆波兰计算器)
- Emacs的lisp lib包: calc
- 基于GTK+的galculator (页面存档备份,存于互联网档案馆)
- 表达式转换[4] (页面存档备份,存于互联网档案馆)
- scratch
注释
[编辑]- ^ 課程名稱:程式設計 - 中序轉後序、前序. sites.google.com. [2022-08-22]. (原始内容存档于2022-08-22) (中文(中国大陆)).
- ^ "Charles L. Hamblin and his work" 互联网档案馆的存檔,存档日期2008-12-06. by Peter McBurney
- ^ "Charles L. Hamblin: Computer Pioneer" 互联网档案馆的存檔,存档日期2008-12-07. by Peter McBurney, July 27, 2008. "Hamblin soon became aware of the problems of (a) computing mathematical formulae containing brackets, and (b) the memory overhead in having dealing with memory stores each of which had its own name. One solution to the first problem was Jan Lukasiewicz's Polish notation, which enables a writer of mathematical notation to instruct a reader the order in which to execute the operations (e.g. addition, multiplication, etc) without using brackets. Polish notation achieves this by having an operator (+, *, etc) precede the operands to which it applies, e.g., +ab, instead of the usual, a+b. Hamblin, with his training in formal logic, knew of Lukasiewicz's work."
- ^ "As was demonstrated in the Algebraic mode, it is usually easier (fewer keystrokes) in working a problem like this to begin with the arithmetic operations inside the parentheses first."[1] (页面存档备份,存于互联网档案馆)
参见
[编辑]参考
[编辑]- RPN or DAL? A brief analysis of Reverse Polish Notation against Direct Algebraic Logic (页面存档备份,存于互联网档案馆) – By James Redin
- Postfix Notation Mini-Lecture (页面存档备份,存于互联网档案馆) – By Bob Brown
- Fith: An Alien Conlang With A LIFO Grammar – By Jeffrey Henning
- Good Ideas, Through the Looking Glass - By Nick Wurth