書式
bc [ -hlwsqv ] [long-options] [ file ... ]バージョン
このマニュアルは GNU bc version 1.06 について記述してあります。解説
bc は、任意の精度の数値を扱う事ができ、プログラミング言語 C の文法に よく似た形の入力を対話的に実行する言語です。 コマンドラインのオプションの指定により、標準数学ライブラリを使用することも できます。これを指定した場合は、どのファイルを処理するよりも前に 数学ライブラリが定義されます。 bc は動作を開始するとまず最初にコマンドラインで指定したファイルを 順に処理します。すべてのファイルを処理した後は、bc は 標準入力からの読み込みを行います。すべてのコードは、それが読み込ま れた時点で実行されていきます。(もし、ファイル中にプロセッサを止める コマンドが含まれていた場合は、標準入力からの読み込みは行われません。)本バージョンの bc は、伝統的な bc の実装および POSIX のドラフト規格よりも拡張されています。コマンドラインオプションにより、 これらの拡張に対して警告を表示したり拒絶したりすることが可能です。 本ドキュメントでは、このプロセッサが受理する言語について説明します。 拡張機能についてはその旨明記します。
オプション
- -h, --help
- 使用方法を表示し、終了します。
- -i, --interactive
- 対話モードを強制します。
- -l, --mathlib
- 標準数学ライブラリを定義します。
- -w, --warn
- POSIX bc に対する拡張機能が入力された場合は警告を出します。
- -s, --standard
- POSIX bc の言語仕様に厳密に従って処理します。
- -q, --quiet
- GNU bc 導入メッセージを表示しません。
- -v, --version
- バージョン番号と著作権を表示して終了します。
数
bc における最も基本的な要素は `数' です。数は、整数部と小数部があり、 任意の精度をとることができます。すべての数は、内部では 10 進数で表現されており、 計算も 10 進数で行われます。(本バージョンでは、除算と乗算で結果に切捨てが 起こります。) 数には length と scale という 2 つの属性があります。 length は 10 進での有効桁数で、scale は小数点以下の 10 進での有効桁数です。 例えば、- .000001 は、lengthが 6 で、scale も 6 です。 1935.000 は、lengthが 7 で、scale が 3 です。
変数
数は、単純変数と配列の 2 種類の変数に保存されます。単純変数と配列変数には共に 名前が付けられます。この名前は、最初の 1 文字目がアルファベットで、後は、 アルファベット、数字およびアンダスコアを任意の文字数組み合わせて 使うことができます。すべてのアルファベットは小文字でなければなりません。 (アルファベットと数字を使った名前の機能は拡張機能です。 POSIX bc では、変数に英小文字 1 文字しか許されません。) 配列変数の名前には必ずブラケット ([]) がつくので、変数の型は文脈において はっきりしています。特殊な変数として scale, ibase, obase, last の 4 つの変数があります。 scale で計算時の小数点以下の有効桁数を指定します。 scale のデフォルトは 0 です。 ibase と obase で入力および出力の変換基数を指定します。 デフォルトでは、入力、出力の基数は共に 10 です。 last は、最後に bc が出力した数を保持しています (これは拡張機能です)。これらについては、後で適切なところで詳しく説明します。 これらの変数には、式で使われる代入と同様の代入を行うことが可能です。
コメント
bc は、/* から */ の間をコメントとして扱います。 コメントはどこから始まっていてもよく、1 文字の空白として扱われます。 (これにより、コメントはその前後の入力アイテムを切り離します。たとえば、 変数名の途中にコメントを置くことはできません。) コメントの中にはいくつ改行があってもかまいません。bc をスクリプトとしても使えるようにするため、1 行コメントが 拡張機能として追加されました。1 行コメントは # で始まり、 次の改行まで有効です。その改行文字自体はコメントの一部とはみなされず、 普通に処理されます。
式
`数' は、式および文によって操作されます。 この言語は対話的になるように設計されているため、 文および式は可能な限り即座に実行されます。 "main" プログラムといったものはなく、そのかわり、コードは それに出くわした時点で実行されます。 (後で述べる`関数'は、それに出くわした時点で定義されます。)式の最も単純なものは、ただの定数です。bc は、入力された 定数を、変数 ibase で指定される現在の基数を元に、内部的には 10 進表現の 数に変換します。(関数の場合には例外があります。) ibase には、2 から 16 までが使用できます。 この範囲を越える値を ibase に代入しようとすると、 2 あるいは 16 を指定したことになります。 数の入力には、0-9 および A-F の文字が利用できます。(注意: これは大文字でなければなりません。小文字は変数名です。) 1 桁の数は ibase の値に関係なくその値を持ちます (すなわち A=10)。 複数桁の数の場合、bc は ibase 以上の値をもつすべての入力桁を ibase-1に変更します。これにより、数 FFF は常に、 その入力基数を使って 3 桁で表現可能な最大の値を表します。
すべての演算式が、他の多くの高級言語に似たものとなっています。 数の型は 1 種類しかないため、型変換の規則はありません。 そのかわり、式の有効桁数に関する規則があります。 すべての式に有効桁数があり、これはその被演算数の有効桁数と 施される演算、それに多くの場合、 変数 scale から決定されます。scale には、0 から C の整数で表現できる最大の値までが指定可能です。
以下、bc で使用可能な演算子を説明します。なお、完全形の式を "expr"、 単純変数または配列変数を "var" と表記します。 単純変数は単に
- name
- name[expr]
- - expr
- 結果はその式の符号を反転したものとなります。
- ++ var
- 変数を 1 だけインクリメントし、その新しい値が式の結果となります。
- -- var
- 変数を 1 だけデクリメントし、その新しい値が式の結果となります。
- var ++
- 式の結果はその変数の値となり、それからその変数を 1 だけ インクリメントします。
- var --
- 式の結果はその変数の値となり、それからその変数を 1 だけ デクリメントします。
- expr + expr
- 式の結果は 2 つの式の和となります。
- expr - expr
- 式の結果は 2 つの式の差となります。
- expr * expr
- 式の結果は 2 つの式の積となります。
- expr / expr
- 式の結果は 2 つの式の商となります。 結果の scale は変数 scale の値となります。
- expr % expr
- 結果は、以下のようにして求められる剰余です。a%b を求めるために、まず a/b を scale の有効桁数で計算します。この結果を用いて、a-(a/b)*b を、 scale+scale(b) と scale(a) の大きい方の有効桁数で計算します。 もし scale に 0 がセットされ、両方の式が整数であれば、 整数の剰余が求められます。
- expr ^ expr
- 式の結果は、1 番目の式の値を 2 番目の回数だけ乗じたものになります。 2 番目の式は、整数でなければなりません。 (2 番目の式が整数でない場合は警告が表示され、 整数に切り詰めた値が使用されます。) 結果の scale は、べき指数が 負なら scale になります。べき指数が正なら、 "1 番目の式の scale とべき指数との積" および "scale と 1 番目の式の scale の大きい方" のうちの小さい方 (つまり、scale(a^b) = min(scale(a)*b, max( scale, scale(a)))) となります。 expr^0 は常に 1 を返します。
- ( expr )
- 標準の優先度を使わずに、この式の評価を優先します。
- var = expr
- 式の値が変数に代入されます。
- var <op>= expr
- "var" が一度しか評価されないこと以外は "var = var <op> expr" と同じです。 "var" が配列の場合は動作が違うことがあり得ます。
関係演算は特殊な演算で、結果は常に 0 か 1 になります。関係が偽の時 0、 真の時 1 になります。関係演算は、演算式のどこでも使う事ができます。 (POSIX bcでは、関係演算は、if, while, for 文の中だけで、しかも 1 つの関係式しか使用できません。) 関係演算子は以下の通り。
- expr1 < expr2
- expr1 が expr2 より小さい場合 1 になります。
- expr1 <= expr2
- expr1 が expr2 より小さいか等しい場合 1 になります。
- expr1 > expr2
- expr1 が expr2 より大きい場合 1 になります。
- expr1 >= expr2
- expr1 が expr2 より大きいか等しい場合 1 になります。
- expr1 == expr2
- expr1 と expr2 が等しい場合 1 になります。
- expr1 != expr2
- expr1 と expr2 が等しくない場合 1 になります。
論理演算も使えます。(POSIX bc には論理演算はありません。) 論理演算も関係演算と同様、結果は 0 か 1 (各々偽および真) になります。 論理演算子は以下の通り。
- !expr
- expr が 0 なら 1 になります。
- expr && expr
- expr1 と expr2 が両方とも 0 でないなら、1 になります。
- expr || expr
- expr1 と expr2 のどちらか一方が 0 でないなら、1 になります。
各演算子の優先順位と結合規則は次の通りです。 (最初のものほど低く、後にいくほど高い優先順位で先に実行されます。)
- || (左から結合) && (左から結合) ! (結合せず) 関係演算 (左から結合) 代入演算 (右から結合) + - (左から結合) * / % (左から結合) ^ (右から結合) - (単項マイナス) (結合せず) ++ -- (結合せず)
この優先順位は、POSIX bc のプログラムがそのまま正しく動くように 配慮して決められています。このため、関係演算と論理演算を 代入文と共に用いた場合、通常とは異なる振る舞いをします。 次の例を考えてみましょう:
- a = 3 < 5
C プログラマのほとんどは、 ``3 < 5'' の関係演算が実行された結果 (つまり 1) が変数 ``a'' に代入される、 と考えるでしょう。 ところが bc では、まず 3 が変数 ``a'' に代入され、 それから 3 と 5 の比較が行われるのです。 この間違いを避けるために、 関係演算や論理演算を代入演算と共に用いる場合は、 括弧を使うのが最良です。
bc には特別な式がさらにいくつか備わっています。 それはユーザ定義関数と標準関数に関するもので、 すべて "name(parameters)" という形をしています。 ユーザ定義関数については関数の章を参照して下さい。 標準関数は以下の通りです:
- length ( expression )
- expression の有効桁数を返します。
- read ( )
- (拡張機能) 関数の出現位置に関係なく、標準入力から数を読み取ります。 データとプログラムの両方を標準入力から与えるような場合には、 問題を生じうることに注意して下さい。 最良の方法は、 ユーザからデータの入力の必要があるなら、プログラムはあらかじめ作っておき、 標準入力からプログラムを入力しないようにすることです。 read 関数の値は標準入力から読み込んだ数です。 その際、変換基数として変数 ibase の現在の値が用いられます。
- scale ( expression )
- expression の小数点以下の有効桁数を返します。
- sqrt ( expression )
- expression の平方根を返します。 expression に負の値を指定した場合は、ランタイムエラーになります。
文
文は (ほとんどの算術言語がそうであるように)、処理を順番に実行していく単位です。 bc では文は「できるだけ早い段階で」実行されます。 改行が入力された時点で、実行可能な文が存在していれば、即座に実行します。 このため bc では改行が重要な役割を持っています。 実際、セミコロンと改行が文の区切りとして使用されます。 不適当な場所で改行を入力すると、文法エラーになります。 改行は文の区切りですが、バックスラッシュを用いて改行を隠すことができます。 bc にとって、"\<nl>" (<nl>は改行) は改行ではなく空白に見えます。 文のリストは、セミコロンと改行で区切られた文の並びです。 以下、bc の文の種類とその動作について説明します。 (なお、以下の説明で ([]) で括った部分は省略可能な項です。)- 演算式
- 演算式には次の 2 つの種類があります。 演算式が "<variable> <assignment> ..." で始まっていれば、 それは代入文として扱われます。 そうでなければ、演算式は評価されて出力に表示されます。 結果が表示された後、改行が表示されます。 例えば、"a=1" は代入文であり、 "(a=1)" は代入文が埋め込まれた演算式です。 表示される数値はすべて、変数 obase で決まる基数で表示されます。 obase に指定できる値は 2 から BC_BASE_MAX までです。 (「制限」の章を参照。) 基数 2 から 16 まででは、通常の数表記法が用いられます。 基数が 16 より大きい場合、bc は、 各桁を 10 進表記する複数桁文字表記法で表示します。 複数桁文字表記法では、各桁は空白で区切られます。 各桁は "obase-1" を 10 進で表記するのに必要な桁数の数字から成ります。 数の精度は任意に選べるため、数によっては 1 行に表示できない場合もあります。 そのような長い数は、行末に "\" を付けて次行に継続します。 1 行に表示できる文字数は 70 です。 bc の対話的性質により、ある数を表示すると、 表示した値が特殊変数 last に代入されるという副作用が生じます。 ユーザはタイプし直すことなく最後に表示された値を再利用できます。 last に値を代入することも可能で、 その場合、前回表示された値が代入値で上書きされます。 新しく代入した値は、次に数が表示されるか別の値が last に代入される まで有効です。(bc の実装によっては、 数の一部になっていない単一のピリオド (.) を last の短縮表記として 用いることができます。)
- string
- 文字列 string が出力に表示されます。 文字列は二重引用符で始まり、次の二重引用符までのすべての文字を含みます。 改行を含め、すべての文字は文字通りに解釈されます。 文字列の後に改行は出力されません。
- print list
- print 文 (これは拡張機能です) は、もうひとつの出力方法です。 "list" はコンマで区切った文字列および演算式のリストであり、 各文字列あるいは演算式がリストの順に表示されます。 最後に改行は出力されません。 演算式は評価され、その値が表示されるとともに、 変数 last に代入されます。 print 文中の文字列は出力に表示されますが、特殊文字を含めることができます。 特殊文字はバックスラッシュ (\) で始まります。 bc で使える特殊文字は、 "a" (ベル)、"b" (バックスペース)、 "f" (フォームフィード)、"n" (改行)、"r" (復帰)、"q" (二重引用符)、 "t" (タブ)、"\" (バックスラッシュ) です。 これ以外は無視されます。
- { statement_list }
- 複文です。複数の文を 1 つのグループにまとめて実行します。
- if ( expression ) statement1 [else statement2]
- if 文は演算式 expression を評価し、その値に応じて 文 statement1 または文 statement2 を実行します。 expression の値が 0 でなければ statement1 が実行されます。 statement2 が存在し、expression の値が 0 ならば、statement2 が実行されます。 (else 節は拡張機能です。)
- while ( expression ) statement
- while 文は expression が 0 でない間、繰り返し statement を実行します。 statement の実行前に毎回 expression を評価します。 expression の値が 0 になるか、break 文を実行すると、 ループが終了します。
- for ( [expression1] ; [expression2] ; [expression3] ) statement
-
for 文は statement の繰り返し実行を制御します。
expression1 はループ実行の前に評価されます。
expression2 は statement の実行前に毎回評価され、
その値が 0 でなければ statement が実行されます。
expression2 の値が 0 になると、ループは終了します。
各 statement 実行の後、再び expression2 が評価される前に expression3 が
評価されます。
expression1 あるいは expression3 が省略されていると、
そこでは何も評価されません。
expression2 が省略されている場合、expression2 が 1 であるのと
同様に扱われます。
(各 expression が省略可能なのは拡張機能です。
POSIX bc では、3 つの expression はどれも省略できません。)
以下は for 文と等価なコードです:
- expression1; while (expression2) { statement; expression3; }
- break
- それを含む最も内側の while もしくは for 文による繰り返しを強制的に中断します。
- continue
- それを含む最も内側の for 文における次の繰り返しに進みます。 (continue 文は拡張機能です)
- halt
- 実行されると bc プロセッサを終了させます(拡張機能)。 例えば "if (0 == 1) halt" の場合は bc は終了しません。 halt 文が実行されないからです。
- return
- 関数から戻ります。関数の結果は 0 になります。(関数の章を参照)
- return ( expression )
- 関数から戻ります。関数の結果は expression になります。(関数の章を参照) 拡張機能ですが、括弧は必須ではありません。
疑似文
これらは今までの文とは動作が異なります。 疑似文は実行文ではなく、「コンパイル」時点で処理されます。- limits
- bc のローカルバージョンにより制限される限界値を表示します。 (limits は拡張機能です)
- quit
- bc を終了します。どんな場所にあっても、quit 文は 入力された時点で実行されます。例えば、 "if (0 == 1) quit" という記述であっても、bc は終了します。
- warranty
- 保証に関する注意を長めに表示します。 (warranty は拡張機能です)
関数
関数は、後で実行されるべき計算手順を定義する機能です。 bc の関数は常に値を計算し、それを呼びだし側に返します。 関数定義は、それが入力から読み込まれた時点で定義が行われるという点で 「ダイナミック(動的)」です。 一度定義された関数は、同じ名前で別の関数が定義されるまで使用可能で、 新しい関数が定義された場合は、前の関数が置き換えられます。 関数の定義は、以下のように行います:- define name ( parameters ) { newline auto_list statement_list }
パラメータ parameters は数あるいは配列 (拡張機能) です。 関数定義では、0 あるいは 1 個以上のパラメータ名を コンマで区切って並べることで定義します。 数は値渡し(call by value)でのみ渡され、配列は変数渡し(call by variable)で のみ渡されます。 配列はパラメータ定義中で "name[]" のように表記して指定します。 関数呼び出しでは、数のパラメータに対して完全な演算式の実パラメータを 記述します。 配列を渡す表記は配列パラメータ定義と同様です。 名前付き配列は変数(variable)によって関数に渡されます。 関数定義はダイナミックゆえ、 パラメータの数と型は関数呼び出しの際にチェックされます。 パラメータの数あるいは型に何らかの不整合があると、 ランタイムエラーが発生します。 未定義関数を呼び出した場合もランタイムエラーとなります。
auto_list は省略可能で、ローカル変数として使用する変数のリスト です。auto_list が存在するなら、その文法は "auto name, ... ;" となります。(セミコロンは省略可能です。) 各 name がローカル変数の名前となります。 配列はパラメータと同様の表記で指定できます。 これらの変数は、関数の最初でその値がスタックにプッシュされたのち 値 0 に初期化され、関数の実行中に使用されます。 これらの変数は関数出口にてポップされ、 (関数呼び出し時の)元の値が復元されます。 パラメータは実際にはローカル変数であり、 関数呼び出しで与えられた値に初期化されます。 bc のローカル変数は伝統的な意味でのローカル変数と異なり、 関数 A が関数 B を呼び出しているような場合、関数 B の中に 関数 A のローカル変数と同じ名前のローカル変数がない限り、 関数 A のローカル変数名をそのまま使って、 関数 B から関数 A のローカル変数をアクセスできます。 ローカル変数とパラメータはスタックにプッシュされるため、 bc は再帰的な関数呼び出しをサポートしています。
関数本体は bc の文のリストです。 繰り返し述べますと、文はセミコロンか改行で区切られています。 return 文により関数は終了し、値を返します。 return 文には 2 つの形式があり、 ひとつめの形式 "return" は、呼び出し元に値 0 を返します。 もうひとつの形式 "return ( expression )" は、 expression の値を計算し、それを呼び出し元に返します。 各関数の最後には "return (0)" があるものと解釈されます。 これにより、明示的に return 文を置かなくても、 関数は終了して値 0 を返します。
関数の中では、変数 ibase の動作が変わります。関数の中で使われて いる定数は、関数の呼びだし時点の ibase を元に変換が行われます。 このため、関数内部で ibase を変更しても無視されます。ただし、標 準関数 read を呼び出した場合は例外で、これは常に現在の ibase の値をもとに変換が行われます。
拡張機能ですが、定義の書式が若干緩やかになりました。 標準では、開くブレースが define キーワードと同じ行にあることと、 他の部分が引き続く行にあることが必須です。 本バージョンの bc では、関数の開くブレースの前後の改行数は任意です。 例えば、次の定義は合法です。
- define d (n) { return (2*n); } define d (n) { return (2*n); }
数学ライブラリ
bc に -l オプションを付けて起動した場合は、数学ライブラリが 読み込まれ、デフォルトの scale が 20 に設定されます。 数学関数は、それを呼び出した時点の scale の値に従って計算を行います。 数学ライブラリによって使用可能になる関数は、次の通りです:- s (x)
- sin (x の単位はラジアン)
- c (x)
- cos (x の単位はラジアン)
- a (x)
- atan (返り値の単位はラジアン)
- l (x)
- log (自然対数)
- e (x)
- exp (指数関数)
- j (n,x)
- 整数 n 次のベッセル関数
使用例
次の例は、/bin/sh でシェル変数 pi に ``パイ'' の値を代入します。- pi=$(echo "scale=10; 4*a(1)" | bc -l)
次の例は、数学ライブラリで使われている ``e (x)'' の定義です。 この関数は POSIX bc で記述されています。
- scale = 20 /* Uses the fact that e^x = (e^(x/2))^2 When x is small enough, we use the series: e^x = 1 + x + x^2/2! + x^3/3! + ... */ define e(x) { auto a, d, e, f, i, m, v, z /* Check the sign of x. */ if (x<0) { m = 1 x = -x } /* Precondition x. */ z = scale; scale = 4 + z + .44*x; while (x > 1) { f += 1; x /= 2; } /* Initialize the variables. */ v = 1+x a = x d = 1 for (i=2; 1; i++) { e = (a *= x) / (d *= i) if (e == 0) { if (f>0) while (f--) v = v*v; scale = z if (m) return (1/v); return (v/1); } v += e } }
次の例は、bc の拡張機能を使って、``checkbook balances'' (小切手帳残高) を計算する簡単なプログラムです。 このプログラムをファイルにしておくと、 毎回タイプしなおさずに何度も使うことができます。
- scale=2 print "\nCheck book program!\n" print " Remember, deposits are negative transactions.\n" print " Exit by a 0 transaction.\n\n" print "Initial balance? "; bal = read() bal /= 1 print "\n" while (1) { "current balance = "; bal "transaction? "; trans = read() if (trans == 0) break; bal -= trans bal /= 1 } quit
次の例は、再帰呼び出しにより階乗を計算する関数です。
- define f (x) { if (x <= 1) return (1); return (f(x-1) * x); }
readline と libedit のオプション
GNU bc は (configure のオプションによって) GNU readline 入力エディタライブラリまたは BSD libedit ライブラリ を使うようにコンパイルできます。 これは、bc に入力する前に、行の編集を可能にします。 以前に入力した行のヒストリも利用可能になります。このオプションで コンパイルされた bc では、さらに 1 つの特殊な変数 history が追加され、ヒストリに保存される行の数を指定します。 readline では、 その値が -1 (デフォルト値)なら、ヒストリ行は制限なく保存されます。 正の数を指定すると、ヒストリ行がその数に制限されます。 0 ならヒストリ機能が無効になります。 デフォルト値は 100 です。 詳しくは、ユーザマニュアルの GNU readline と history ライブラリと BSD libedit をご覧下さい。 readline と libedit の両方を同時に有効化できません。相違点
このバージョンの bc は POSIX P1003.2/D11 ドラフトから実装されており、 そのドラフトや以前の実装に比べていくつかの相違点や拡張点があります。 伝統的に行われていたような dc(1) を用いた実装ではありません。 このバージョンは単一プロセスであり、 プログラムをバイトコードに変換したものを解析して実行します。 「ドキュメントに記載されていない」オプション (-c) があり、 プログラムを実行する代わりに、それをバイトコードに変換した結果を 標準出力に出力します。 これは主として、パーザのデバッグと数学ライブラリの準備に用いられました。主な相違点は拡張機能によるものです。 機能を高めたり追加したりするために機能が拡張されたり、 新機能が追加されたりしています。 相違点と拡張点のリストを以下に示します。
- LANG
- このバージョンは、 環境変数 LANG および LC_ で始まるすべての環境変数の処理に関して POSIX 標準に 準拠していません。
- 名前
- 伝統的な bc および POSIX bc は、関数、変数、配列の名前として単一の文字を使います。 このバージョンでは、 先頭が文字で始まり、文字と数字とアンダースコアで 構成される 2 文字以上の名前が使えるように拡張されています。
- 文字列
- 文字列には NUL 文字を含むことはできません。 POSIX では、文字列にはあらゆる文字を含めることができなければならない、 としています。
- last
- POSIX bc には変数 last はありません。 bc の実装によっては、last と同じ意味で ピリオド (.) を用いるものがあります。
- 比較
- POSIX bc では、比較は if 文、while 文、for 文の第 2 式の中でのみ 用いることができます。 また、これらの文の中ではただ 1 つの関係演算しか使えません。
- if 文, else 節
- POSIX bc には else 節はありません。
- for 文
- POSIX bc では for 文の各演算式は省略できません。
- &&, ||, !
- POSIX bc には論理演算子はありません。
- read 関数
- POSIX bc には read 関数はありません。
- print 文
- POSIX bc には print 文はありません。
- continue 文
- POSIX bc には continue 文はありません。
- return 文
- POSIX bc では、return 文の周りに括弧が必要です。
- 配列パラメータ
- POSIX bc では (現在のところ) 配列パラメータは完全には使えません。 POSIX の文法では、関数定義では配列を使えますが、実際に呼び出すときの パラメータに配列を指定することができません。(これはおそらく、文法上の 見落としでしょう。) 伝統的な bc の実装では、配列パラメータは値渡し のみでした。
- function format
- POSIX bc では、開くブレースが define キーワードと同じ行にあり、 auto 文が次の行にあることが必要です。
- =+, =-, =*, =/, =%, =^
- POSIX bc ではこれらの「旧式」の代入演算子を定義する必要はありません。 このバージョンではこれらの「旧式」代入演算子が使えるかも知れません。 limits 文を使って、インストールしたバージョンがこれらをサポートしているか どうか、確かめてみて下さい。 もしそのバージョンが「旧式」代入演算子をサポートしていれば、 文 "a =- 1" は a に値 -1 を代入する代わりに a を 1 減じます。
- 数字表記中の空白
- 他の bc 実装では、数字表記の中に空白を含めることが許されます。 例えば、"x=1 3" は変数 x に値 13 を代入します。 このバージョンの bc では、先の文は文法エラーになります。
- エラーと実行
-
このバージョンの bc は、
プログラムに文法上のエラーや他のエラーが見つかった場合に
どういうコードが実行されるか、
という点で、他の実装と異なっています。
ある関数定義中で文法エラーが見つかると、
エラー回復機構は文の先頭を見つけて関数のパーズを続けようと努力します。
ひとたび関数の中で文法エラーが見つかると、
その関数は呼び出せなくなり、未定義状態となります。
対話的実行コードで文法エラーがあると、
現在の実行ブロックが無効になります。
実行ブロックとは、ひと続きの完全な文のあとの行末までのことです。
例えば、次のコード
- a = 1 b = 2
- { a = 1 b = 2 }
- 割り込み
- 対話セッションの間、SIGINT シグナル (通常、端末からの Control-C 入力で 発生します) によって現在の実行ブロックの実行が中断され、 どの関数が中断されたかを示す「ランタイム」エラーが表示されます。 ランタイムのデータ構造をすべてクリアした後メッセージが表示され、 bc は次の入力を受け付ける状態になったことを示します。 これまでに定義した関数はすべて定義されて残っており、 ローカルでない変数の値は割り込み発生時点の値のままになっています。 ローカル変数と関数パラメータはすべて、クリア処理によって消去されます。 非対話セッションでは、SIGINT シグナルで bc の実行全体が終了します。
限界
以下の項目が現在の bc プロセッサの限界値となっています。 このうちいくつかは、インストール時に変更できます。 実際の値を得るには limits 文を使って下さい。- BC_BASE_MAX
- 現在のところ、出力の基数の最大値は 999 に設定されています。 入力側の基数の最大値は 16 です。
- BC_DIM_MAX
- 現在のところ 65535 として配布されていますが、 インストールしたバージョンでは異なっているかも知れません。
- BC_SCALE_MAX
- 小数点以下の桁数は INT_MAX 桁に制限されています。 また、小数点より上の桁数も INT_MAX 桁に制限されています。
- BC_STRING_MAX
- 文字列中の文字数は INT_MAX 文字に制限されています。
- 指数
- 累乗演算 (^) の指数の値は LONG_MAX に制限されています。
- 変数名
- 単純変数、配列、関数各々について、一意に識別される名前は 32767 個に 制限されています。
環境変数
bc は以下の環境変数を解釈します。- POSIXLY_CORRECT
- -s オプションと同じです。
- BC_ENV_ARGS
- これは bc に引数を渡す別の方法で、コマンドライン引き数と 同じ書式です。この引数が最初に処理されるので、この環境変数で 指定されたファイルはコマンドライン引数で指定されたファイルよりも 先に処理されます。これにより、毎回 bc を呼び出すごとに 処理する「標準の」オプションやファイルを設定できます。この環境変数で 指定するファイルには、bc を走らせるたびに定義しておきたいような 関数の定義を書いておくとよいでしょう。
- BC_LINE_LENGTH
- 数字を出力するときの 1 行の文字数を整数で指定します。 数字が長過ぎると、バックスラッシュと改行を含めた出力となります。
診断
コマンドラインで指定したファイルがオープンできない場合、 bc はファイルが利用できない旨を表示して終了します。 また、コンパイル時あるいはランタイムの診断メッセージもありますが、 それらは自身で理解できるようになっているはずです。バグ
エラーリカバリがまだうまくいっていません。バグ報告は、 [email protected] に電子メールでお願いします。 単語 ``bc'' を ``Subject:'' フィールドのどこかに入れておいてください。
作者
Philip A. Nelson [email protected]
謝辞
実装をテストする際に 広範囲に手助けしてくれた Steve Sommars ([email protected]) に感謝します。 たくさんの素晴らしい意見をもらいました。 彼のおかげでとてもよいものになりました。