FreeBSD QandA 587

FreeBSD QandA

Q. gccで "long double" を使用して数値計算を行ないましたが、同じ CPU での 
   Linux の結果と比べて計算精度が悪く、計算結果が異なります。

A. FreeBSD の標準カーネルでは浮動小数点の仮数部の精度が (IEEE754 と異なり)
   53bit に設定されているために起きる現象です。

   long double の仮数部の精度は64bitです。(double の仮数部の精度は 53bit です)

   Intel x86 系の FPU の仮数部の精度は 24/53/64bit に設定可能です。
   FreeBSD では仮数部の精度が 53bit に設定されているために、long double
   を使用しても仮数部の精度が 53bit (つまり、double と同じ) しかありません。

   精度を上げて数値計算を行なうには:

   1. 関数 fpsetprec()/fpgetprec() を使用して、FPU の仮数部の精度を 64bit 
      に変更する事が出来ます。fpsetprec(3) を御覧下さい。

   2. GNU Multiple Precision Arithmetic Library (GMP)、PARI 等 FreeBSD 標
      準以外の数値演算ライブラリを利用してもよいでしょう。

   1. fpsetprec()/fpgetprec() について

   FreeBSD users MLの以下のメールから始まるスレッドが参考になるでしょう。
     Subject: [FreeBSD-users-jp 24352] gcc bug
     Subject: [FreeBSD-users-jp 46648] long double
   その他、オンラインマニュアル fpsetround(3)math(3)ieee(3)などが参考
   になります。
   ただし、fpsetprec は double の内部演算も 64bit 精度にしてしまうという
   副作用があります。double での演算結果が変わってしまう可能性がありますの
   で注意して下さい。

   long double 使用上の注意点:
    * FreeBSD の printf(3) は 5.1-RELEASE から long double に対応しました。
      それ以前 (少なくとも 4.8-RELEASE までと、5.0-RELEASE) は、書式で "%Lf"
      等を使用してもエラーにはなりませんが、double の精度でしか表示されません。
    * long double 用の算術関数 sqrtl(), sinl() 等が標準で用意されていません。
      ([管理番号 588] 参照)

   プログラム例:
   ----------------------------
   #ifdef __FreeBSD__
   #include <ieeefp.h>
   #endif

      ...

   int main()
   {
     long double tmp1, tmp2;
      ...

   #ifdef __FreeBSD__
     fpsetprec(FP_PE); /* 仮数部の精度を 64bit にする。 */
   #endif
      ...
   }
   ----------------------------

   2. 非標準の数値演算ライブラリについて

   GMP (ports/math/libgmp4) は、任意多倍長の整数、整数を法とした計算 
   (modular arithmetic)、有理数、浮動小数点数の四則などが出来ます。但し、
   三角関数、対数関数などの初等的な関数もないので、用途が限られるかも知れ
   ません (自分で頑張って書けば、勿論問題ないですが)。

   PARI (ports/math/pari) は、GMP 同様の数の他、p 進数や、それぞれの数
   を係数とした多項式、羃級数、行列やベクトルの計算ができ、初等超越関数 
   (三角関数や指数対数関数) の他、これでもかというくらい様々な関数が実装
   されています。本来は、整数論用のライブラリ集 (と、対話的に計算するため
   の gp というコマンド (bc の様な感じ)) で、ちょっとした用途には大げさ
   かも知れません。

   いずれも C から使うことになるでしょう。(PARIは、Fortran や Pascal から
   も使えるようです)。

   他に参考になるものとしては
     SAL: <URL:http://SAL.linet.gr.jp/index.shtml>
   があります。

同一グループへのリンク

グループ名: FreeBSD-math


間違い・追加情報を見付けた場合は、 修正案の投稿のしかた を読んだ上で、
QandA@jp.FreeBSD.org まで お知らせください。