アットウィキロゴ

dcProgramming

「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
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。