bc [–i] [–l] [file]
bc は、算術計算を任意の精度で実行できるプログラム言語です。これは、端末から命令を入力することによって、対話式に使用することができます。また、ファイルから取り出したプログラムを実行することもできます。
コマンド行に指定された file 引数は、bc 命令を含む テキスト・ファイルでなければなりません。 bc は、これらのファイルからの命令をコマンド行に現れる順序で実行し、その後で標準入力 (stdin) からの命令を実行します。 bc は、quit 命令を実行したとき、または 標準入力 (stdin) のファイルの終わりに達したときに 終了します。
bc は、単純ではあるが完全なプログラム言語であり、構文が C プログラミング 言語に似ています。bc の本バージョンは、多くのシステムで使用可能な 標準言語のスーパーセットです。これは、この言語をより柔軟性の高い、役に立つ言語にするための、多くの追加機能を持っています。このインプリメンテーション (実装) 独自の機能については、注意書きがしてあります。
入力は、変数に値を割り当て、あるいは計算を行う、一連の命令によって 構成されます。関数 と呼ばれるサブプログラムを定義することもできます。この関数は、1 つの値を計算するために一連の命令を実行します。
2+2
4
デフォルトにより、bc は評価した命令の結果を表示したあとで改行します。bc はまた、最後に表示した値を特殊変数 . (ドット) に 保管するので、次の計算で それを使用することができます。
このコマンドに対する UNIX03 での変更の要約については、UNIX03 用に変更されたシェル・コマンドを参照してください。
数は、任意の負 (-) 符号または任意の正 (+) 符号に続いてゼロまたはそれ以上の数字のシーケンス、続いて任意の小数点 (.)、続いてゼロまたはそれ以上の数字のシーケンスにより構成されます。有効な数字は、0 から 9、および A から F の 16 進数 です。大文字は、10 から 15 の値を表してい ます。小数点の前か後のいずれかに、少なくとも 1 つの数字がなければ なりません。そうでない場合は、bc は小数点 を (前述のように) 特殊変数 . と解釈します。
0 0. .0 -3.14159 +09. -12 1 000 000
0 FF FF.3 -10.444 A1
詳細は、Bases を参照してください。
制約事項: 数値をコンマで区切ることはできません。1000000 または 1 000 000 と書くことはできますが、1,000,000 と書くとエラー・メッセージが出ます。
ID には、任意の数の文字、数字、または下線 (_) 文字のシーケンスを含めることができますが、小文字で始めなければなりません。 ID 内では、スペースは認められません。
POSIX ロケールでは、現行のロケールのように、有効な ID には任意の数の文字、数字、または下線 (_) 文字のシーケンスを含めることができますが、小文字で始めなければなりません。
a[3] a[3.2] a[3.999]
bc 配列内のエレメントの最大数は、0 から {BC_DIM_MAX}-1 の範囲 (両端も含む) です。他の多くの言語と異なり、配列のサイズを宣言する必要はありません。エレメントは必要に応じて動的に作成され、初期値はゼロになります。
関数の名前の後には必ず括弧が続き、配列の名前の後には必ず大括弧が続くため 、bc は 3 つのタイプの名前 (変数名、関数名、および配列名) をすべて 区別することができます。したがって、同じ名前の変数、関数、および配列を使用することができます。例えば、foo は変数であり、foo() は関数、foo[ ] は配列となります。
bc には多くの組み込み変数があり、インタープリターのさまざまな局面を制御するために使用されます。この後のトピックでこれらを説明します。
5 / 3
が、以下の値であることを意味しています。1.666
–l が指定された場合、スケールは 20 に設定されます。それ以外の場合、デフォルトのスケールはゼロです。
scale = 5
scale は通常の bc 変数と同じなので、bc の式の どこででも使用することができます。
計算結果の小数点以下の桁数は、スケールだけでなく、計算のオペランドの小数点以下の桁数によっても 影響されます。これについては、算術演算子を参照してください。
scale という関数もあります。これは、任意の式のスケールを判別するために使用することができます。例えば、scale(1.1234) は 4 という結果を戻します。これは、数 1.1234 のスケールです。scale 関数の結果は、常に整数です (すなわち、スケールは 0 です)。
scale の最大値は、構成変数 {BC_SCALE_MAX} によって与えられます。最小値は 0 です。
bc では、異なる基数 (例えば、8 進数 (基数 8) または 16 進数 (基数 16)) で数を指定することができます。 1 つの基数で数を入力し、それを異なる基数で出力することができるので、別の基数に数を変換するという作業が簡単になります。bc は、組み込み変数 ibase と obase を使用して これを行います。
ibase = 8
ibase = A
obase は、数が出力されるときの基数です。その初期値は 10 (通常の 10 進数) です。出力基数を変更するためには、obase に適切な整数を 割り当ててください。
123 456 789
この場合、数字は 0 から 999 の 10 進数値です。その結果、出力されるすべての値は、1 つまたはそれ以上のチャンク (塊) (1 つのチャンクごとに 3 つの 数字) に分けられます。10 の大きな累乗を出力基数に使用すると、出力を欄に分けて並べることができます。例えば、100 000 はよい出力基数になります。これは、数がそれぞれ 5 桁のチャンクにグループ化されるからです。
長い数は、1 行当たり最大 70 文字で出力されます。 数がこれより長い場合、bc は、その行の末尾に円記号 (¥) を入れて、 数が次の行に続くことを示します。円記号 (¥) および改行文字は、70 文字の文字長の一部としてカウントされます。
入力および出力の基数に関係なく、内部の計算は 10 進で行われます。したがって、小数点の後の桁数は、数が 10 進形式で表されたときのスケールによって決められます。
obase の最大値は、構成変数 {BC_BASE_MAX} によって与えられます。
bc では、多くの算術演算が提供されています。標準の算術の規則に従って、いくつかの演算は他の演算よりも先に行われます。例えば、演算を括弧でグループ化しない限り、乗算は加算よりも先に行われます。先に行われる演算は、後で行われる演算よりも より高い優先順位 を持っていると言われます。
bc の優先順位は、C と同じではありません。C では、割り当て演算子は最も低い優先順位を持っています。
min(scale(A) * abs(B), max(scale, scale(A)))
ここで、min は一組の数の最小値を計算し、max は最大値を計算します。
min(scale(A) + scale(B), max(scale, scale(A), scale(B)))
A - (A / B) * B
max(scale + scale(B), scale(A))
以下の演算子は、すべて割り当て 演算子です。これらはオブジェクトに値を割り当てます。割り当て演算は、値を持っています。その値は、割り当てられている値です。
/* Any string */
2+2 # this is a comment
a = 2¥
+ 3
a = 2 + 3
3.14 * 23
a = 3.14 * 23
と入力すると、bc は何も表示しません。これは式が割り当てだからです。代入式の値を表示したい場合は、単に式を括弧で囲んでください。
"Hello world!"
foo = 15
"The value of foo is "; foo
The value of foo is 15
{
statement
statement
…
}
中括弧は、数行に分割された一連の文を グループにすることができます。中括弧は、通常、if や while のような 制御ステートメントと共に使用されます。
initexp
while (relation) {
statement
endexp
}
a = 0
for (i = 1; i <= 10; ++i) a += i
は、前記の while の例と同等です。規則: 括弧内の 3 つの項目は、すべて指定する必要があります。C と異なり 、bc ではこれらの式を省略することはできません。
if ((a%2) == 0) "a is even"
は、a が偶数の値である場合に a is even と 表示します。
if ((a%2) == 0) "a is even" else "a is odd"
“a is even” と else キーワードとの間に文分離文字はありません。これは C 言語と異なります。
if (a<10) {
"a "
"is "; "less than 10 "
a
} else {
"a is"
" greater than 10 "
a
}
規則: 中括弧は、if および else キーワードと 同じ行にある必要があります。これは、(relation) の直後に改行またはセミコロンがあると、文のボディがヌルであることを示すからです。bc プログラムによくあるエラーの原因は 、if ステートメントのボディ部分を別の行に入力することです。–i が使用された場合、インタープリターは、ボディ部分がヌルの if ステートメントを検出したときに、警告を表示します。
i = 1
a = 0
while (i <= 10) { a += i
++i
}
は、1 から 10 の整数を加算し、結果を a に格納します。
bc が while ループを検出したときに relation が真でなかった場合は 、bc は statement を実行しません。
/* basic print statement */
print "The square of ", 2, "is ", 2*2
The square of 2 is 4
/* inserts a space between adjacent numbers */
print 1,2,3
1 2 3
/* note - no spaces */
print 1,"",2,"",3
123
/* just print a blank line */
print
/* two statements with output on same line */
print 1,2,3, ; print 4, 5, 6
1 2 3 4 5 6
sh more <foo
このコマンドは、最初の非ブランク文字から行の終わりまでのすべてを、実行のためにコマンド・インタープリターに送ります。
void foo++
は foo を増やしますが、結果は表示しません。void ステートメントは、このバージョンの bc に固有なものです。
他のいくつかのタイプの文は、関数定義のみに関係しています。これらは、次のトピックで説明されています。
define f_to_c(f) {
return ((f-32) * 5 / 9)
}
return (expression)
は、expression の値を関数の結果として戻します。expression の前後の括弧は任意です。
name(expression,expression,…)
ここで、name は関数の名前、expression は関数の引数の値です。 関数呼び出しは、他の式のどこででも使用することができます。関数呼び出しの値は、関数が戻す値です。例えば、前に説明した f_to_c() では 、f_to_c(41) の値は 5 です (これは、華氏 41 度が摂氏 5 度に等しいからです)。
define name(parameter,parameter,…) {
auto local, local, …
statement
statement
…
}
define cmpvec(a[],b[]) {
パラメーターは、同じ名前の配列または変数と競合しません。例えば、関数の内部に a という名前のパラメーターがあり、外部に a という名前の変数がある場合、2 つは全く別のエンティティーとみなされます。変数に値を割り当ててもパラメーターは変更されません。逆も同様です。すべてのパラメーターは、値で渡されます。このことは、引数値のコピーが作成されて、仮パラメーターに 割り当てられることを意味します。 これは、配列にも適用されます。関数に配列を渡すと、配列全体からコピーが作成されますので、配列パラメーターに対して行われる変更は、元の配列に影響しません。
define f() {
auto ステートメントは、一連のローカル 変数を 宣言します。変数名または配列名が auto ステートメント内に現れた場合、これらの項目の現行値は保管され、項目はゼロに初期化されます。関数の実行中は、項目には新しい値が入ります。関数が終了したとき、項目の古い値が復元されます。
しかし、bc は動的スコープの規則に従い、字句スコープ規則を使用する C とは異なります。 詳細は、使用上の注意 を参照してくだ さい。
define addarr(a[],l) {
auto i, s
for (i=0; i < l; ++i) s += a[i]
return (s)
}
define func_with_local_array() {
auto local_array[];
for(i=0; i<100; i++) local_array[i] = i*2
}
この例は、local_array と呼ばれるローカル配列を定義しています。ローカル配列は、最初はその中にエレメントがありません。
define sum_c(a[ ],b[ ],l) {
auto i
for (i=0; i < l; ++i) c[i] = a[i] + b[i]
}
は、c と名付けられた外部配列を参照します。これは、他の 2 つの配列のエレメントごとの合計です。sum_c を呼び出す前に c が存在していなかった場合は、動的に作成されます。プログラムが sum_c 文を呼 び出した後は、プログラム内または関数内のステートメントは配列 c を 参照することができます。
return (expression)
引数 expression が評価され、関数の結果として使用されます。 式は単一の数値を持っていなければなりません。配列であってはなりません。
define abs(i) {
if (i < 0) return (-i)
return (i)
}
は、引数の絶対値を戻す関数です。 i がゼロより小さい場合は、関数は最初の return を 採用し、それ以外の場合は 2 番目を採用します。
関数は、関数内の最後のステートメントを実行することによっても終了します。その場合は、関数の結果はゼロです。関数 sum_c は、return ステートメントのない 関数の例です。この関数は return ステートメントを必要としません。これは、その機能が外部配列 c を計算することであり、単一の値を計算することではないためです。最後に、関数からは戻りたいが、値を戻したくない場合は、return() または単に return とします。return ステートメントにパラメーターがない場合は、デフォルト値ゼロが戻されます。
これらの関数が返す結果の scale 値は、関数が呼び出された時点での scale 変数の値になります。これらの関数が実行を完了した後の scale 変数の値は、呼び出し時の値と同じ値になります。
define sales_tax(purchase,tax) {
auto old_scale
scale = 2
tax = purchase*(tax/100)
scale = old_scale
return (tax)
}
sales_tax(23.99,6)
は、$23.99 の購入に対する 6% の税額を計算します。関数は、金額が小数点以下 2 桁まで計算されるように、スケールの値を一時的に 2 に設定します。bc では計算結果は切り捨てられ、四捨五入は行われないことを 思い出してください。そのため、正確性は多少失われます。必要な桁数よりもう 1 桁多く使用して、最後の桁で四捨五入を行う方がよいと考えられます。このトピックの後の方で示される round2 関数は、数を小数点以下 2 桁に四捨五入します。
define integer_part(x) {
# a local to save the value of scale
auto old_scale
# save the old scale, and set scale to 0
old_scale = scale; scale=0
# divide by 1 to truncate the number
x /= 1
# restore the old scale
scale=old_scale
return (x)
}
define fractional_part(x) {return (x - integer_part(x))}
define set_scale(x, s)
{ auto os
os = scale
scale = s
x /= 1
scale = os
return (x) }
define round2(num) {
auto temp;
if(scale(num) < 2) return (set_scale(num, 2))
temp = (num - set_scale(num, 2)) * 1000
if(temp > 5) num += 0.01
return (set_scale(num,2))
}
define sales_tax(purchase,tax) {
auto old_scale
scale = 2
tax = round2(purchase*(tax/100))
scale = old_scale
return (tax)
}
define fact (x) {
if(x < 1) return 1
return (x*fact(x-1))
}
define fact (x) {
auto result
result = 1
while(x>1) result *= x--
return (result)
}
いずれの場合でも、fact(6) は 720 を戻します。
define fib(n) { if(n < 3) { return (1)
} else {
return (fib(n-1)+fib(n-2))
}
}
a=10
define f1() {
auto a;
a = 13;
return (f2())
}
define f2() {
return (a)
}
f1()
13
f2()
10
f1() が呼び出されると、bc は 10 ではなく、13 を出力します。これは、f1() が a の古い (グローバルの) 値を 隠して、13 に設定するためです。f2() が a を参照するときには、f1() によって 動的に作成された変数を見、そして 13 を出力します。f1() は、終了するときに a を前の値に復元し ます。f2() が、f1() を介してではなく、直接呼び出された場合は、a のグローバル値を 見るので 10 を出力します。対応する C コードでは、両方の場合とも 10 を出力します。
define ten() {
return (10)
}
ten()
10
ibase=16
ten()
16
この例では、基数が 10 に設定されているときには、ten() は 10 進値の 10 を戻します。しかし、入力基数が 16 に変更されると、関数は 10 進値の 16 を戻します。このことは、bc プログラムでの混同によるエラーの 原因になる可能性があります。
詳しくは、ローカライズを参照してください。
構文解析プログラムのスタックの深さは、150 レベルまでに制限されます。非常に複雑なプログラムを処理しようとすると、このスタックがオーバーフローして、エラーの原因になる可能性があります。
POSIX.2, X/Open 移植性ガイド, UNIX システム.
2 バイト環境では、POSIX 文字セットからの数字と演算子のみが使用できること に注意してください。ID は現行のロケールからの文字を使用できます。スクリプトを移植可能にしたい場合は、POSIX からの文字だけを使用してください。