4

いくつかの大学の仕事のために、私はいくつかの数を概算する必要があります-シリーズのオイラーのもののように。したがって、非常に小さな数を追加する必要がありますが、精度に問題があります。数が非常に少ない場合は、結果に影響しません。

real s;  //sum of all previous terms
ulong k; //factorial

s += 1.0/ k;

各ステップの後、kはさらに小さくなりますが、第10ラウンドの後、結果はそれ以上変化せず、2.71828でスタックします。

4

3 に答える 3

9

floatCPUの浮動小数点ユニット( 、、 )でネイティブにサポートされている固定精度の浮動小数点型は、double指定realした例のように、何桁もの精度を必要とする計算には最適ではありません。

問題は、これらの浮動小数点型の精度が有限の桁数(実際には2桁)であるため、このようなデータ型で表すことができる数値の長さが制限されることです。このfloatタイプには、小数点以下7桁の制限があります(例:3.141593)。タイプは14に制限されていdoubleます(例:3.1415926535898)。タイプにも同様の制限がありrealます(の制限よりわずかに多いdouble)。

したがって、浮動小数点値に非常に小さい数値を追加すると、それらの桁が失われます。次の2つのfloat値を合計するとどうなるかを見てください。

float a = 1.234567f, b = 0.0000000001234567
float c = a + b;

writefln("a = %f b = %f c = %f", a, b, c);

aとは両方ともb有効な浮動小数点値であり、個別に約7桁の精度を保持します。ただし、追加すると、フロートに押し戻されるため、最前面の7桁のみが保持されます。

1.2345670001234567 => 1.234567|0001234567 => 1.234567
                              ^^^^^^^^^^^
                         sent to the bit bucket

したがって、加算からの精度のより細かい桁が打ちのめさcれるため、に等しくなります。aab

これが概念の別の説明です。おそらく私のものよりはるかに優れています。


この問題に対する答えは、任意精度の演算です。残念ながら、任意精度演算のサポートはCPUハードウェアにはありません。したがって、(通常は)プログラミング言語ではありません。ただし、任意精度の浮動小数点型とそれらに対して実行する計算をサポートするライブラリは多数あります。いくつかの提案については、この質問を参照してください。今日、この目的のためのD固有のライブラリはおそらく見つかりませんが、単独で使用するのに十分簡単なはずのCライブラリ(GMP、MPFRなど)がたくさんあります。それらの1つのDバインディング。

于 2011-02-09T14:58:05.433 に答える
3

ネイティブタイプを使用して実行されるソリューションが必要な場合は、常に同じ大きさの数値を追加しようとすることで、妥当な結果を得ることができるはずです。これを行う1つの方法は、級数の最初のX項を計算してから、2つの最小の数値を合計で繰り返し置き換えることです。

auto data = real[N];
foreach(i, ref v; data) {
  v = Fn(i);
}

while(data.length > 1) {
  data.sort(); // IIRC .sort is deprecated but I forget what replaced it.
  data[1] += data[0];
  data = data[1..$];
}

return data[0];

(最小ヒープはこれを少し速くします。)

于 2011-02-10T15:15:20.483 に答える
2

すでに述べたように、サードパーティの多精度浮動小数点演算ライブラリを使用する必要があります(TangoまたはPhobosには、任意の長さの整数演算用のモジュールしかないと思います)。

dilはMPFRを使用するDプロジェクトです。そこにバインディングが見つかるはずです。

于 2011-02-10T17:03:09.497 に答える