Bc (UNIX)bc(ビーシー)は、Unixで広く使われている、中置記法の算術式を計算する任意精度演算プログラムおよびその入力言語である。式はコマンドライン引数として与えることもできるし、標準入力などから与えることもできる。例えば、 POSIXで標準化されている[1]が、これを大幅に拡張したGNU版の実装もある。Plan 9版は、標準のスーパーセットでGNU版のサブセットになっている。そのほか、オリジナルのUNIX版の実装[2]や、OpenBSDプロジェクトで実装されたもの(他にFreeBSDなどで使われている)が主要な実装である。 Windows用などのバイナリが配布されているものもある。 標準bcは伝統的に、後置記法(逆ポーランド記法)のdcというプログラムのフロントエンドプロセスとして実装されてきた。標準も、それに倣った実装を考慮して定義されているが、必ずそのように実装しなければならない、とはしていない。後述するGNU版ではbcとdcはそれぞれ別のプログラムとして実装されている。bcをdcと連携させる実装において、bcとdcのどちら側を親プロセスとするかは実装によって異なる。 言語要素には、1文字の変数名・配列名・関数名、ほとんどの標準的演算子、よくある制御構造としてC言語にあるもの(if文、whileループ、forループ)が備わっている。なお、C言語とは異なり、if文にはelse節がない。 関数の定義にはキーワード 全ての数と変数の中身は任意精度数であり、その精度(十進での桁数)は大域変数 対話型モードでの入力と出力やプログラム内の定数の底(基数)は、予約された変数 計算結果を変数に格納しないと、そのまま出力として結果が表示される。 BASIC言語のような対話型での利用を想定されているため、文の終わりは改行(LF)が必要。セミコロン ; などをつけると文法エラーとなる。 コメントは、C言語と同様に 演算子C言語と同じ演算子以下の演算子は、C言語と同じ作用をする。
C言語と類似する演算子剰余演算子
は、大域変数 C言語と意味が異なる演算子"^" や "^=" という演算子は、C言語ではビット単位の排他的論理和だが、bcではべき乗演算子(ただし、べき指数は整数)である。 C言語にあるがbcにない演算子次の、ビット演算子、ブーリアン演算子、比較演算子などは、標準には存在しない。
組み込み関数標準では唯一の組み込み関数として 数学関数-l オプションで追加される数学関数には、三角関数(正弦、余弦、逆正接)、自然対数、指数関数、2引数のベッセル関数 J が含まれる。ほとんどの標準的関数(逆正弦関数や逆余弦関数など)は、これらを使って構築できる。他の関数の実装については、外部リンクを参照。 なお、-l オプションでは、それと同時に、scaleが20に設定される。そのため剰余演算が思わぬ結果を返すことがある。例えば、"bc -l" として、"print 3%2" と入力すると、1ではなく0と出力する。しかし、"bc -l" で起動した後で "scale=0" とすれば、"print 3%2" は1を出力する。 Plan 9版Plan 9版は標準とほぼ同じだが、 GNU版GNU版では数々の拡張を加えられている。また、dcのフロントエンドではなく、独立したプロセスとして動作する実装である。しかし、標準とは互換性を保っており、標準bc用プログラムは修正なしでGNU版でも実行できる。 変数、配列、関数の名前は1文字に制限されない。また、C言語の演算子もさらに導入されていて、特にif文にはelse節を書くことができる。 出力は、標準と同様に計算結果を変数に代入しないときにも表示されるし、 さらに、 C言語風のコメント以外に、 直近の計算結果は常に組み込み変数 追加された演算子以下の論理演算子が追加されている。
これらは 関数関数については、標準と同じである。 コード例bcの 標準の bc によるべき乗関数/* x の整数部分を返す関数 */ define i(x) { auto s s = scale scale = 0 x /= 1 /* x を丸める */ scale = s return (x) } /* x^y == e^(y*log(x)) という性質を使う */ define p(x,y) { if (y == i(y)) { return (x ^ y) } return ( e( y * l(x) ) ) } GNU版のbcによる同等のべき乗関数# 数の整数部分を返す関数 define int(number) { auto oldscale oldscale = scale scale = 0 number /= 1 /* 丸める */ scale = oldscale return number } # number^exponent == e^(exponent*log(number)) という性質を利用 define power(number,exponent) { if (exponent == int(exponent)) { return number ^ exponent } else { return e( exponent * l(number) ) } } 円周率を1万桁まで計算する(高野の公式(1982年)を使用)(「高野の公式」を参照) $ bc -l -q scale = 10000; (12*a(1/49)+32*a(1/57)-5*a(1/239)+12*a(1/110443))*4 C言語の関数をbcに変換するbc の文法はC言語とよく似ているので、Cで書かれたアルゴリズムは容易に bc に翻訳可能であり、それによって bc の任意精度の恩恵を受けることができる。例えば、Journal of Statistical Software (July 2004, Volume 11, Issue 5) には、George Marsaglia の論文に累積正規分布に関する次のC言語コードが掲載されていた。 double Phi(double x)
{
long double s=x,t=0,b=x,q=x*x,i=1;
while(s!=t)
s=(t=s)+(b*=q/(i+=2));
return .5+s*exp(-.5*q-.91893853320467274178L);
}
これは簡単にGNU bc用に書き換えることができ、次のようになる。 define normal(x)
{
auto s,t,b,q,i,const;
const=0.5*l(8*a(1));
s=x;
t=0;
b=x;
q=x*x;
i=1;
while(s!=t) {s=(t=s)+(b*=q/(i+=2))};
return .5+s*e(-.5*q-const);
}
シェルスクリプトでのbcの利用bcは非対話的に使うこともでき、入力はパイプで供給する。シェルスクリプトで使う場合に便利である。例えば、 $ result=$(echo "scale=2; 5 * 7 / 3;" | bc) $ echo $result 11.66 あるいは、入力はヒアドキュメントでも構わない。 $ bc <<! scale=2 5 * 7 / 3 ! 11.66 その他数値の指数表記(たとえば 1.23e-17 のように定数を記述したり、入出力をする機能)は備わっていない。 脚注・出典
参考文献
外部リンク
Information related to Bc (UNIX) |