Dc (程序)

title: 历史.
content: dc是幸存的最老的Unix语言。在贝尔实验室收到第一台PDP-11的时候,用B语言写成的dc是在这个新机器上运行的第一个语言,甚至在汇编器之前。
title: 基本操作.
content: 在dc中要做4和5的乘法:  $ dc 4 5 * p 20 q  这可转译为“把4和5压入栈顶,通过乘法算符,从栈中弹出两个元素,将二者相乘并把结果压回栈顶”。接着使用codice_1命令打印栈顶的元素。使用codice_2命令退出此次调用的dc实例。注意数值相互间必须以空白分隔,但某些算符可以不必如此。 还可以用如下命令得到这个结果:  $ dc -e '4 5 * p' 20 $ echo "4 5 * p" |dc 20 $ dc - 4 5*pq 20 $ cat «EOF > cal.txt 4 5 * p EOF $ dc cal.txt 20  使用命令codice_3来变更算术精度,它设置算术运算的小数位数。因为缺省精度是codice_4,例如:  $ dc -e "2 3 / p" 0  通过使用命令codice_3调整精度,可以产生任意数目的小数数位,例如:  $ dc -e "5 k 2 3 / p".66666  dc有科学计算器的基本运算功能,比如求formula_1的值:  $ dc -e "2k 12 _3 4 ^ + 11 / v 22 - p" -19.10  其中,codice_6用于输入负数,codice_7计算幂,codice_8计算平方根。  使用codice_9命令复制栈顶元素。使用codice_10命令对栈顶和仅次栈顶的两个元素进行对换。使用codice_11命令压入当前栈深度,即执行codice_11命令前栈中元素的数目。
title: 输入/输出.
content: 使用codice_13命令,从stdin读取一行并执行它。这允许从宏中向用户要求输入,故而此输入必须是语法上正确的,并且这有潜在的安全问题,因为dc的codice_14命令可以执行任意系统命令。  前面提及过,codice_1命令打印栈顶元素,带有随后的一个换行。codice_16命令弹出栈顶元素并输出它,没有尾随换行。codice_17命令打印整个栈,一项一行。  dc还支持控制输入和输出的基数。codice_18命令弹出栈顶元素并将它用作输入基数。十六进制数字必须大写以避免和dc命令冲突,输入基数必须在2和16之间,输出基数必须大于等于2。codice_19命令设置输出基数,要记住输入基数将影响对后面的所有数值的分析,所以通常建议先设置输出基数。例如将二进制转换成十六进制:  $ echo 16o2i 11011110101011011011111011101111p | dc DEADBEEF  要读取设置的这些数值,codice_20、codice_21和codice_22命令将压入当前精度、输入基数和输出基数到栈顶。
title: 语言特征.
content: 除了上述的基本算术和栈操作,dc包括了对宏、条件和存储结果用于以后检索的支持。
title: 寄存器.
content: 寄存器在dc中是有着单一字符名字的存贮位置,它可以通过命令来存储和检索,它是宏和条件的底层机制:codice_23弹出栈顶元素并将它存储入寄存器codice_24,而codice_25将寄存器codice_24的值压入栈顶。例如: <syntaxhighlight> </syntaxhighlight> 寄存器还被当作次要栈,可以使用codice_27和codice_28命令在它们和主要栈之间压入和弹出数值。存储栈顶元素到寄存器中并把这个元素留在栈顶,需要联合使用codice_29命令。
title: 字符串.
content: 字符串是包围在codice_30和codice_31之中的字符,可以被压入栈顶和存入寄存器。使用codice_32命令从栈顶弹出字符串并执行它,使用codice_33命令从栈顶弹出并打印字符串,无尾随换行。codice_34命令可以把数值的低位字节转换成ASCII字符,或者在栈顶是字符串时把它替换为这个字符串的第一个字符。此外没有方法去建造字符串或进行字符串操纵。  codice_35字符开始一个注释直到此行结束。
title: 宏.
content: 通过允许寄存器和栈项目像数值一样存储字符串,从而实现了宏。一个字符串可以被打印,也可以被执行,就是说作为dc命令的序列而传递。例如可以把一个宏“加1并接着乘以2”存储到一个寄存器codice_36中: <syntaxhighlight> </syntaxhighlight> 通过使用codice_32命令弹出栈顶的字符串并执行之,如下这样使用存储的宏: <syntaxhighlight> </syntaxhighlight> codice_38命令从栈顶弹出一个值作为退出宏的层数,比如codice_39命令退出2层宏,它永不导致退出dc。codice_2命令退出2层宏,如果宏少于2层则退出dc。
title: 条件.
content: 最后提供了有条件执行宏的机制。命令codice_41将从栈顶弹出两个值,如果二者相等,则执行存储在寄存器codice_10中的宏。如下命令序列将在原栈顶元素等于5的条件下打印字符串codice_43。 <syntaxhighlight> [[equal]p] sm d 5 =m </syntaxhighlight>  这里使用了codice_9命令保留原栈顶元素。其他条件有codice_45、codice_46、codice_47、codice_48、codice_49,如果栈顶元素分别大于、不大于(小于等于)、小于、不小于(大于等于)、不等于仅次于栈顶的元素,则执行指定宏。
title: 迭代.
content: 通过定义有条件的调用自身的[[递归]]宏,[[迭代]]也是可行的。一个简单的对栈顶元素的[[阶乘]][[子程序|过程]]: <syntaxhighlight> </syntaxhighlight> 可实现为: <syntaxhighlight> </syntaxhighlight> 这里宏中的第一个codice_9命令相当于分配了一个局部变量。
title: 例子.
content: [[Unix]] [[Version 7 Unix|V7]]手册页举出的编程实例为打印[[阶乘]]n!的前10个值:  $ dc [la1+dsa*pla10>y]sy 0sa1 lyx 1 2 6 24 120 720 5040 40320 362880 3628800  这个程序实现了[[For循环]],将作为循环体的宏codice_51存储在寄存器codice_52中;把寄存器codice_34作为[[循环计数器]],设其初始值为codice_4,将0!的值codice_55压入栈顶;从寄存器codice_52中取出宏并执行之。宏中的codice_57将计数器codice_34的数值加codice_55,并将这个值留在栈顶;随后codice_60从栈中弹出两个元素进行乘法并把结果压入栈中,打印这个结果;随后codice_61将计数器codice_34的数值和数值codice_63压入栈中,判断位于栈顶的codice_63是否大于计数器的数值,即计数器的数值是否小于codice_63,弹出二者并在判断成立的条件下再次执行存储在寄存器codice_52中的宏。计数器codice_34的数值从codice_4增加到codice_63,宏一共被执行了codice_63次。
title: 外部链接.
content: [[Category:面向堆栈编程语言]] [[Category:跨平台软件]] [[Category:Unix软件]] [[Category:软件计算器]] [[Category:自由数学软件]] [[Category:数值分析语言]]

Summary: dc(desk calculator:桌面计算器)是采用逆波兰表示法的跨平台计算器,它支持任意精度算术。它是最老的Unix实用工具,先于C语言的发明。像那个年代的其他实用工具一样,它有着一组强力的特征和简洁的语法。传统上,采用中缀表示法的bc计算器程序是在dc之上实现的。

Dc (computer program): dc ("desk calculator") is a cross-platform reverse-polish calculator which supports arbitrary-precision arithmetic. Written by Robert Morris while at Bell Labs, it is one of the oldest Unix utilities, preceding even the invention of the C programming language. Like other utilities of that vintage, it has a powerful set of features but terse syntax. Traditionally, the bc calculator program (with infix notation) was implemented on top of dc.