「dcProgramming」の編集履歴(バックアップ)一覧に戻る
dcProgramming - (2010/09/06 (月) 21:50:41) のソース
*dc Programming
**はじめに
***dcについて
dc は、arbitrary precision desk calculator であり、reverse Polish notation (RPN) を採用しているのが特徴である。今は使われていないかもしれないが、UNIX で配布されている。また、[[bc>bcProgramming]] というのもあるが、これは、C language like syntaxを特徴とし、かつては、dc用のprogram filesをoutputできたらしいが、GNU BC では、独立したプログラムとなっており、残念ながら、できない。
*** dcとForth
同じ RPN を採用しており、スタックが重要であることは共通しているが、やはり、微妙に異なる。dc の manual を見ないと書けない。
**dc
***導入
終了 q C-c
起動 command-line options
-e 'expr'
--expression='expr'
'expr' as dc [[commands]]
-f 'file'
--file='file'
read and evaluate dc commands from 'file'
オプションの後に、パラメーターが残っている場合は追加fileとして解釈され、その内容が評価される。特に '-' というファイル名は standard input stream を指す。
***数とarbitrary precision
decimal point 以下の数字の数(precision value)は default で 0、すなわち整数である。例えば、小数点以下20桁まで表示するとすれば、20k と入力する。負の数は'_'を使う。'-' は substraction という binary operation である。また、実数は小数形式であり、exponential notation はない。
*** commands
- printing commands
'p' print TOS with a newline. TOS remains. (TOS=top of stack)
'n' print TOS without a newline. TOS is popped off. (GNU extension)
'P' print TOS without a newline. TOS is popped off.
if a string, print it.
if numbers <= 256 print the ASCII character
if numbers > 256 print the value of the number modulo 256
'f' print the entire contents of the stack without altering anything.
*** arithmetic
+ - * / % ^
'~' quotient & remainder
'|' pops three values and computes the modular exponentiation.
reduction modulus, exponent, base(GNU extension)
'v' square root
*** stack control
'c' clear stack
'd' duplicate
'r' swap the top two values on the stack. (GNU extension)
*** registers
'sr' store TOS into register r, popped TOS off.
'lr' push the value of register r, without popping off.
'Sr' push TOS into register r as TOS of register r.
'Lr' push TOS of register r onto the main stack.
*** parameters
'i' input radix
'o' output radix
input radix must be between 2 and 16 inclusive.
outp radix must be at least 2. hexadecimalのとき、A through Fも使う。
注意)input radixをhexadecimalにして、再度、decimalに戻すときは、Aiと入力する。
1000 o
123456789 p => 123 456 789
100000 o
123456789 p => 01234 56789
*** strings
dcはstringsについては、printするか、macroとして実行する。
registersでもstackでもstringsを保存できる。
[characters] eg) '[foo]P' prints 'foo' with no newline
'a' asciify eg)42ap=>* 13ap=>Carridge Return
'x' pop the value off the stack and execute as a macro .
if it is a number, simply pushing back onto the stack.
'>r' pops two values off the stack and compares them,
if TOS is greater, execute the contents of register r.
eg) '1 2>a' => invoking register 'a''s contents
'!>r' not greater
'=r' if equal
'?' allows a macro to request input from the user
'q' exit
'Q' pops a value off the stack and uses it
as a count of levels of macro execution to b
*** status inquiry
'Z' number of digits (ignoring minus sign and decimal point)
or number of characters X number of fraction digits .for a string, 0.
'x' current stack depth: the nubmer of objects on the stack
before the execution of 'z' command.
***miscellaneous
'!' run a system command
'#' the rest of the line as a comment (GNU extension)
':r' store in the array r eg)<value><index>:r
';r' push from the array r. eg)<index>;r =><value>
**サンプルプログラム
dc のサンプルプログラムはインターネットで探してもほとんど見つからない。
Morris & Cherry のmanualより
# print the number 0-9
[lip1+ si li10a>]sa
0si lax
ibm aixのcommands referenceより
# factorial of n 最初の1行は1との大小で実行するマクロを切り替えていることに注意。
[d 1 >b d 1 <r] sf # if 1>n do b; if 1<n do r
[d 1 +] sb # return f(n)=n*f(n-1)
[d 1 - lf x *]sr # return f(n)=n*f(n-1)
10 lf x p => 3628800
5 lf x p => 120
注)comment である"#"はGNU extension
Plan 9 manual
# print the first ten values of n!
[la1+dsa*pla10>y]sy
0sa1 lyx
Ted Faber
# average calculation
0st0sn (t:total, n:number)
[lt+stln1+snz0<az0=d]sa
[ltln/p0st0sn]sd
$dc dc.avg -
5 k
1 2 3 4 5 6 7 8 9 10 lax
5.50000
Everything2.com
# FizzBuzz in dc
[sg []] sX
[
[Buzz] l5 0!=X
[Fizz] l3 0!=X
n p sG
] sA
[ln p sG] sB
[
ln 3 % s3
ln 5 % s5
l3 l5 * d 0=A 0 !=B
ln 1 + d sn
101 > C
] sC
1 sn
lCx
# shorter version
[sg[]]sx1[ddd3%d[Fizz]r0!=xnr5%d[Buzz]r0!=xn*0=xpsg1+dd101>M]dsMx
(注)FizzBuzzとは
one two three ... と続け、ある数の倍数をfizz, buzzに替える。
両方の倍数ならfizzbuzzとする。
MKS Toolkit9.1 Documentation Build7から
# print out the first 12 elements of the Fibonacci sequence
1 sa
1 sb
2 sc
[la lb + p lb sa sb lc 1 + d sc 13 >z] sz
[lr*lr1-dsr0<a]sa
10sr1 lla p sx lp p sx lz x
wikipedia
(1) print the string 'equal' only if TOS=5
[1+2*] sm
3 lm x p
[[equal]p] sm 5 =m
(2) convert from meters to feet and inches
dc -e '[[Enter a number (meters), or 0 to exit]psj]sh[q]sz \
[lhx?d0=z10k39.37009*.5+0k12~1/rn[feet]Pn[inches]P10Pdx]dx' (実際は1行)
(3) Euclidean algorithm for search GCD
dc -e '??[dSarLa%d0<a]dsaxp' # shortest
dc -e '[a=]P?[b=]P?[dSarLa%d0<a]dsax+[GCD:]Pp' # more comfortable version
**私が考えたプログラム例
**factorial
10!
(1) 10sr1[lr*lr1-dsr0<a]dsaxp # two registers
(1)' [lr*lr1-dsr0<a]sa
10sr1 laxp
(2) 1 10[dsr*lr1-d0<a]dsax+p # two registers (注)tosが0となるので、+でしめる。
(3) 1 10[dSa*La1-d0<a]dsax+p # one register
**(1/2)の階乗の計算
(1) (1/2)^1~(1/2)^17
20 k
[2/dli1+dsi:ali17>a]sa
0sil lax
# 計算結果は配列に収納
(2) n=1 0.5000の形で表示
[li1+d[= ]Pn[]Pdsi;an10anli17>b]sb
# '10a'=newline n10anの代わりにpを用いると、stackにデータが残る。
0si lbx