総合手引 | セクション 1 | English | オプション |
本バージョンの bc は、伝統的な bc の実装および POSIX のドラフト規格よりも拡張されています。コマンドラインオプションにより、 これらの拡張に対して警告を表示したり拒絶したりすることが可能です。 本ドキュメントでは、このプロセッサが受理する言語について説明します。 拡張機能についてはその旨明記します。
-h, --help | 使用方法を表示し、終了します。 |
-i, --interactive | 対話モードを強制します。 |
-l, --mathlib | 標準数学ライブラリを定義します。 |
-w, --warn | POSIX bc に対する拡張機能が入力された場合は警告を出します。 |
-s, --standard | POSIX bc の言語仕様に厳密に従って処理します。 |
-q, --quiet | GNU bc 導入メッセージを表示しません。 |
-v, --version | バージョン番号と著作権を表示して終了します。 |
.000001 は、lengthが 6 で、scale も 6 です。 1935.000 は、lengthが 7 で、scale が 3 です。
特殊な変数として scale, ibase, obase, last の 4 つの変数があります。 scale で計算時の小数点以下の有効桁数を指定します。 scale のデフォルトは 0 です。 ibase と obase で入力および出力の変換基数を指定します。 デフォルトでは、入力、出力の基数は共に 10 です。 last は、最後に bc が出力した数を保持しています (これは拡張機能です)。これらについては、後で適切なところで詳しく説明します。 これらの変数には、式で使われる代入と同様の代入を行うことが可能です。
bc をスクリプトとしても使えるようにするため、1 行コメントが 拡張機能として追加されました。1 行コメントは # で始まり、 次の改行まで有効です。その改行文字自体はコメントの一部とはみなされず、 普通に処理されます。
式の最も単純なものは、ただの定数です。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 に負の値を指定した場合は、ランタイムエラーになります。 |
演算式 | 演算式には次の 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 は拡張機能です) |
関数呼び出しは、 "name(parameters)" という形式の演算式です。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); }
s (x) | sin (x の単位はラジアン) |
c (x) | cos (x の単位はラジアン) |
a (x) | atan (返り値の単位はラジアン) |
l (x) | log (自然対数) |
e (x) | exp (指数関数) |
j (n,x) | 整数 n 次のベッセル関数 |
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); }
主な相違点は拡張機能によるものです。 機能を高めたり追加したりするために機能が拡張されたり、 新機能が追加されたりしています。 相違点と拡張点のリストを以下に示します。
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には 2 つの実行ブロックがあり、 { a = 1 b = 2 }には 1 つの実行ブロックがあります。 ランタイムエラーが発生すると、現在の実行ブロックの実行が終了します。 ランタイムの警告が発生しても、現在の実行ブロックは終了しません。 |
割り込み | 対話セッションの間、SIGINT シグナル (通常、端末からの Control-C 入力で 発生します) によって現在の実行ブロックの実行が中断され、 どの関数が中断されたかを示す「ランタイム」エラーが表示されます。 ランタイムのデータ構造をすべてクリアした後メッセージが表示され、 bc は次の入力を受け付ける状態になったことを示します。 これまでに定義した関数はすべて定義されて残っており、 ローカルでない変数の値は割り込み発生時点の値のままになっています。 ローカル変数と関数パラメータはすべて、クリア処理によって消去されます。 非対話セッションでは、SIGINT シグナルで bc の実行全体が終了します。 |
BC_BASE_MAX | 現在のところ、出力の基数の最大値は 999 に設定されています。 入力側の基数の最大値は 16 です。 |
BC_DIM_MAX | 現在のところ 65535 として配布されていますが、 インストールしたバージョンでは異なっているかも知れません。 |
BC_SCALE_MAX | 小数点以下の桁数は INT_MAX 桁に制限されています。 また、小数点より上の桁数も INT_MAX 桁に制限されています。 |
BC_STRING_MAX | 文字列中の文字数は INT_MAX 文字に制限されています。 |
指数 | 累乗演算 (^) の指数の値は LONG_MAX に制限されています。 |
変数名 | 単純変数、配列、関数各々について、一意に識別される名前は 32767 個に 制限されています。 |
POSIXLY_CORRECT | -s オプションと同じです。 |
BC_ENV_ARGS | これは bc に引数を渡す別の方法で、コマンドライン引数と 同じ書式です。この引数が最初に処理されるので、この環境変数で 指定されたファイルはコマンドライン引数で指定されたファイルよりも 先に処理されます。これにより、毎回 bc を呼び出すごとに 処理する「標準の」オプションやファイルを設定できます。この環境変数で 指定するファイルには、bc を走らせるたびに定義しておきたいような 関数の定義を書いておくとよいでしょう。 |
BC_LINE_LENGTH | 数字を出力するときの 1 行の文字数を整数で指定します。 数字が長過ぎると、バックスラッシュと改行を含めた出力となります。 |
バグ報告は、 bug-bc@gnu.org に電子メールでお願いします。 単語 ``bc'' を ``Subject:'' フィールドのどこかに入れておいてください。
Philip A. Nelson philnelson@acm.org
. | bc (1) |
総合手引 | セクション 1 | English | オプション |
このマニュアルページサービスについてのご意見は Ben Bullock にお知らせください。 Privacy policy.