linux下的dc計算器

gaorongchao1990626發表於2013-04-15

dc採用逆波蘭式計算表示式,計算過程是對棧的手動維護。逆波蘭式看起來很彆扭,但跑起來當然是很有效率的。
亂七八糟的東西就不說了,直接切入script正題

負號在dc裡用_表示而非-,因為-是二元運算子“減號”

列印類命令:
p            :列印棧頂元素並換行
n            : 列印棧頂元素並將其彈出棧,完畢後不換行
P            : putchar ( int(棧頂元素) % 256) 並彈棧頂,不換行
f            : 從棧頂至棧底列印棧中所有值,每個一行

算數運算子:
+            : 依次彈出w1與w2,將w2+w1壓棧。精度為結果值精度
-            : 依次彈出w1與w2,將w2-w1壓棧
*            : 依次彈出w1與w2,將w2*w1壓棧。精度為結果值精度與precision中較大值
/            : 依次彈出w1與w2,將w2/w1壓棧。精度為precision
%            : 依次彈出w1與w2,將w2-w2/w1*w1壓棧
~            : 依次彈出w1與w2,依次將w2/w1與w2%w1壓棧
^            : 依次彈出w1與w2,將w2^((int)w1)壓棧。精度為w2精度與precision中較大值
|            : 依次彈出w1 w2與w3,將 w3 ^ ((int)w2) (mod w1) 壓棧。w1 w3 需為整數
v            : 彈出w1,將sqrt(v)壓棧。精度為precision

棧操作:
c            : 清空棧
d            : 將棧頂元素複製並壓棧
r            : 交換棧頂兩元素 XXX

暫存器操作:
dc提供至少256個暫存器,分別用256個字元表示。一般用'a'..'z',不夠可以用123ABC!@#,再不夠就用\x00..\xff
除了主棧外,每個暫存器都是獨立的棧,暫存器棧頂的值被稱為這個暫存器的值
sr           : 彈出主棧頂元素w1,若r棧為空,則將w1壓入r棧,否則將r棧頂元素改為w1
lr           : 將r暫存器的值壓入主棧
Sr           : 彈出主棧頂元素w1,壓入r棧
Lr           : 彈出r棧頂元素w1並將其壓入主棧

引數:
dc有三個引數:輸入進位制 輸出進位制與precision(精度)。precision永遠被作為10進位制來看。
i            : 彈出棧頂w1並將其作為輸入進位制
o            : 彈出棧頂w1並將其作為輸出進位制
k            : 彈出棧頂w1並將其作為precision
I            : 將輸入進位制壓棧
O            : 將輸出進位制壓棧
K            : 將precision壓棧

字串:
dc暫存器可以存放字串,字串可以被列印或被作為dc命令去執行
[characters] : 將字串characters壓棧。characters中可以包含任何字元,除了[]需兩兩匹配
a            : 若棧頂w1是數字,則將棧頂修改為(char)((int)(w1)%256),否則將w1首字母入棧
x            : 若棧頂w1是數字,則什麼都不做,否則將其彈出並將w1作為命令交給dc執行
>r           : 依次彈出w1與w2,若w1>w2則執行r暫存器中的命令
!>r          : 依次彈出w1與w2,若w1<=w2則執行r暫存器中的命令
<r           : 依次彈出w1與w2,若w1<w2則執行r暫存器中的命令
!<r          : 依次彈出w1與w2,若w1>=w2則執行r暫存器中的命令
=r           : 依次彈出w1與w2,若w1==w2則執行r暫存器中的命令
!=r          : 依次彈出w1與w2,若w1!=w2則執行r暫存器中的命令
?            : 從標準輸入讀入一條命令並將其交給dc執行
q            : 終止當前dc與當前dc的呼叫dc
Q            : 彈出棧頂w1,終止w1層dc。當w1大於當前dc層數時會報錯,因此Q不會使主dc退出

狀態查詢:
Z            : 彈出棧頂w1,將w1長度壓棧
X            : 彈出棧頂w1,若w1為數字,則將w1小數位數壓棧,否則將0壓棧
z            : 將當前棧深度壓棧

其他:
!            : 將!之後的部分作為命令交給sh執行。若命令以'>' '='開頭,則需在!後加上空格
#            : 將#之後的部分作為註釋
:r           : 依次彈出w1與w2,r[w1]=w2
;r           : 彈出棧頂w1,將r[w1]壓棧

真正的精髓好像是通過x與opr進行的流程控制,等著再看吧

相關文章