bc (UNIX)

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動: 案内検索

bc(ビーシー)は、C言語に似た文法の「任意精度演算言語」である。通常、UNIXシェルから bc コマンドを直接起動し、数式を入力して使う。例えば、(1 + 3) * 2 と入力すれば 8 と出力する。

現在2つの方言が存在する。1つは厳密に定義されたPOSIX版 bc で、もう1つはそこから派生して拡張を加えたGNU版 bc である(GNU bc は、Microsoft Windows など様々なプラットフォームでも動作する)。また、Plan 9 版 bc は、POSIX版のスーパーセットでGNU版のサブセットになっている。

どの版でも、算術スクリプト言語または対話型算術シェルとして使える。

目次

[編集] POSIX bc

POSIXが標準化したbc言語は dc という電卓ソフトを使って書かれている。dc は逆ポーランド記法で入力するため簡明だが人間が使うには複雑だということで、より抽象化した入力で計算ができるようにしたのが bc である。

bc言語の言語要素には、1文字の変数名・配列名・関数名、ほとんどの標準的演算子、よくある制御構造としてC言語にあるもの(if文、whileループ、forループ)が備わっている。なお、C言語とは異なり、if文にはelse節がない。

関数の定義にはキーワード define を使い、関数の返す値は return の後の括弧内にその値を記述する。関数内で変数が局所変数であることを示すため、auto というキーワードを使って変数を宣言する(C言語ではオプション)。

全ての数と変数の中身は任意精度数であり、その精度(十進での桁数)は大域変数 scale で決まる。

対話型モードでの入力と出力やプログラム内の定数の底(基数)は、予約された変数 ibase (入力)と obase (出力)で指定できる。

計算結果を変数に格納しないと、そのまま出力として結果が表示される。

bcのコードにコメントを付与する場合、C言語と同様に /**/ で囲む。

[編集] 演算子

[編集] C言語と正確に同じ演算子

以下の POSIX bc の演算子は、C言語と同じ作用をする。

  • "+"、"-"、"*"、"/"、"+="、"-="、"*="、"/="、"++"、"--"、"<"、">"、"=="、"!="、"<="、">="、"("、")"、"["、"]"、"{"、"}"

[編集] C言語と類似する演算子

剰余演算子

  • "%"、"%="

は、大域変数 scale が0に設定されているときだけC言語と同じ作用となる。すなわち、精度が0とは整数のみの計算を行うことを意味する。scale が0より大きい場合、商を指定された精度で計算したものに除数をかけて、それを被除数から引いた値となる(ほとんどゼロに近い)。

[編集] C言語の演算子と似ているだけの演算子

"^" や "^=" という演算子は、C言語ではビット単位の排他的論理和だが、bcではべき乗演算子(ただし、べき指数は整数)である。

[編集] C言語にあって bc にない演算子

次の、ビット演算子、ブーリアン演算子、比較演算子などは、POSIX bc には存在しない。

  • "&"、"|"、"^"、"&="、"|="、"^="
  • "&&"、"||"、"^^"、"&&="、"||="、"^^="
  • "<<"、">>"、"<<="、">>="、"?:"

[編集] 組み込み関数

POSIX bc の唯一の組み込み関数として sqrt() がある。他の関数は外部の標準ライブラリの形で提供される。

[編集] 標準ライブラリ関数

bc の標準数学ライブラリ(-l オプションで定義される)には、三角関数(正弦、余弦、逆正接)、自然対数指数関数、2引数のベッセル関数 J が含まれる。ほとんどの標準的関数(逆正弦関数や逆余弦関数など)は、これらを使って構築できる。他の関数の実装については、外部リンクを参照。

なお、-l オプションでライブラリをロードすると、scale が20に設定される[1]。そのため剰余演算が思わぬ結果を返すことがある。例えば、"bc -l" として、"print 3%2" と入力すると、1ではなく0と出力する。しかし、"bc -l" で起動した後で "scale=0" とすれば、"print 3%2" は1を出力する。

[編集] Plan 9 bc

Plan 9 の bc は POSIX bc とほぼ同じだが、print 文が追加されている。

[編集] GNU bc

GNU bc はPOSIX版から派生し、数々の拡張を加えたものである。POSIX版とは異なり、dc をベースとしているわけではなく、C言語で書かれている。それでも POSIX bc に対して完全な互換性を保っており、POSIX bc 用プログラムは修正なしで GNU bc でも実行できる。

GNU bc の変数、配列、関数の名前は1文字に制限されていない。また、C言語の演算子もさらに導入されていて、特にif文にはelse節を書くことができる。

出力は、POSIX版のように計算結果を変数に代入しないときにも表示されるし、print 文で表示させることもできる。

さらに、read 文でプログラムに対話的に数値を入力することもできる。

C言語風のコメント以外に、# から行末までをコメントとして扱う。

直近の計算結果は常に組み込み変数 last に格納されている。

[編集] 追加された演算子

以下の論理演算子が追加されている。

  • &&
  • ||
  • !

これらは if 文の条件節などで使える。なお、ビット演算や代入と組み合わせた演算はやはり存在しない。

[編集] 関数

POSIX bc にあった関数は GNU bc にも継承されている。標準で追加された関数は存在しない。

[編集] コード例

bc の ^ 演算子はべき指数が整数でないと機能しない。bc の利用者がまず書こうとする関数の1つとして、浮動小数点数のべき指数を扱えるべき乗関数が考えられる。次の2つのコード例は、標準ライブラリを使うことを前提としている。

[編集] POSIX 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

[編集] 関連項目

[編集] 脚注・出典

[編集] 参考文献

[編集] 外部リンク