man dc
は用意されてるけど, 全部のコマンドが載ってないようなのでソースコード読みながらまとめる. 読むのは "bc-1.07.tar.gz" です.
入力の基底(進数). 2 以上 16 以下整数. 初期値は 10.
出力の基底. 2 以上. 初期値は 10.
計算の精度. 初期値は 0.
0 から 255 までの ASCII 文字に対応するレジスタが用意されている. その文字でレジスタに名前がついており, いくつかのコマンドはこの名前で指定する.
例えば 61 に対応するのは a
という文字だから, 61 番目のレジスタには a
という名前がついている. 後述する s
コマンドはこの後ろにレジスタ名を続けて指定するので sa
で a
レジスタへの操作を宣言する.
各レジスタは次の3つの用途がある.
実際にはこの 1 つ目は長さ(深さ) 1 のスタックで表現されており 2 つ芽とデータを共有している. 一方で 2 つ目と 3 つ目はたまたま同じ名前が与えられているだけで, 全く別のデータとして確保されている (内部データとしては, どちらも linked list で持ってる).
[_.0-9A-F]*
数値として解釈してスタック. マイナス単符号は _
.
+-*/
2つ値をポップして順に y
, x
とするとき, x op y
を計算してプッシュする.
例えば 3 2 -
は 1
をプッシュする.
%
, ~
%
は単に剰余を取る.
~
は商と余りを両方取る. スタックのトップが余りで二番目に商を置く.
^
, |
^
は単にべき乗を計算する.
|
は剰余を取りながらべき乗計算をする. これはスタックの頭から3つをポップして, 頭から順に mod, exp, base
だとし, base
の exp
乗の mod
剰余を計算してスタックする.
v
値一個をポップして平方根を計算する.
<
, =
>
, !
スタックの頭から2つをポップして順に a
, b
だとするとき, <, =, >
はそれぞれ a < b, a = b, a > b
のとき, 続いて指定するレジスタに入ってる文字列をコマンドとして解釈して実行する. さもなくば何もしない.
!
をこの前につけることで条件を否定できる.
?
一行文字列を読み込んでコマンドとして解釈し実行.
[ ]
[
から対応する ]
を一つの文字列データとしてスタックに積む.
#
#
から行末まではコメント
a
ポップしてきた数値データを ASCII コードで文字に変換してプッシュ.
x
ポップしてきた値を dc のコマンドとして解釈して実行.
i
, I
i
でポップした値を dc_ibase にセット. I
で dc_ibase の値をプッシュ.
o
, O
同様
k
, K
, X
k
でポップしてセット. K
でプッシュ.
X
は現在の dc_scale の値でスタックのトップを上書きする.
s
, S
レジスタ一文字を続けて指定して使う. ポップした値をそこにセットする.
s
はレジスタを一個の値で上書きする. これは一度レジスタを空にしてからプッシュする. S
はレジスタにプッシュする.
l
, L
続いてレジスタ名を一文字で指定して使う. レジスタから値を読み出してプッシュ. l
はレジスタを単に一個の値として読んでプッシュ. L
はレジスタをスタックだとし, スタックからポップした値をプッシュする.
n
, p
, P
n
は 値をポップして出力する. 数値データは数値として出力される. このとき, 改行は出力されない.
p
は値をピークして(ポップせず覗き見るだけ)出力する. 数値データは数値として出力される. このとき改行も出力される.
P
は値をポップして出力する. 数値データは ASCII として解釈して文字で出力する (a
). このとき, 改行は出力されない.
q
, Q
q
で実行から抜け出す. dc の一部のコマンドは再帰的に dc のコマンドを呼び出すため, 実行環境は入れ子構造をしているが, q
は二段階までしか抜け出さない.
Q
はポップしてきた値で何段階抜け出すかを指定する.
c
c
で現在のスタックを空にする.
d
d
でトップの値をプッシュする. (ポップしてその値を2回プッシュする.)
f
スタックの中身を全て表示する:
$ echo 1 2 3 f | dc
3
2
1
r
, R
r
はスタックの頭2つを入れ替える.
R
はまず値をポップし, 数値データ \(n\) を得る. この値は 1 以上の整数か -1 以下の整数でなければならない. \(n\) が 1 以上の場合, この時点でスタックの頭から \(n\) 番目のものをスタックのトップに持ってくる. \(n\) が -1 以下の場合, この時点でスタックの頭にある値を, 頭から \(-n\) 番目にあるように持っていく.
以下に例を示す:
$ echo 1 0 0 3R f | dc
1
0
0
$ echo 0 0 0 1 _3R f | dc
0
0
1
0
z
現在のスタックの長さ(深さ)をプッシュする.
Z
ポップしてきた値のデータ長をプッシュする. データ長の定義は数値ならマイナス符号と小数点を除いた桁数. 文字列ならその長さ.
:
レジスタ名を続く一文字 (a-z
) で指定する. :
は値を 2 つポップする. 順に index
, value
とし, レジスタの配列の index
に紐づく値に value
をセットする.
;
レジスタ名一文字を続けて指定する. 2つ値をポップして index
, value
として紐づく値をプッシュする.