5

C++ で「通常の」実数を考えてみましょうTREAL x(非正規でも NaN/Infinite でもありません) ( TREAL= float, double, long double)以下は、浮動小数点の観点から
前と次を見つける良い解決策ですか?x

TREAL xprev = (((TREAL)(1.)) - std::numeric_limits<TREAL>::epsilon()) * x;
TREAL xnext = (((TREAL)(1.)) + std::numeric_limits<TREAL>::epsilon()) * x;

どうもありがとうございました。

4

4 に答える 4

13

C99 と C++1 には、 と に nextafter、nextafterl、および nextafterf 関数が<math.h>あり<cmath>ます。丸めを考慮する必要があるため、基本的な算術演算とイプシロンでそれらを実装するのは面倒です。バイナリ表現で作業する方がおそらく簡単ですが、符号と大きさの表現の影響と -0.0 の存在について疑問に思います (必要なものについてはFred の回答を参照してください)。

于 2012-06-22T16:14:42.613 に答える
5

次の浮動小数点数を取得することは、バイナリ レベルでははるかに簡単です。

float next(float f)
{
    unsigned x;
    memcpy(&x, &f, 4);
    ++x;
    memcpy(&f, &x, 4);
    return f;
}

もちろん、これは浮動小数点数が「昇順」で格納されるシステムでのみ機能します。これはたまたま IEEE754 の場合です。

負の数は負の無限大に向かっていきます。代わりにゼロに行きたいですか?これを使って:

float next(float f)
{
    int x;
    memcpy(&x, &f, 4);
    x += x >> 31 | 1;   // this will add 1 for positive f and -1 for negative f
    memcpy(&f, &x, 4);
    return f;
}
于 2012-06-22T16:17:24.303 に答える
2

いいえ、「連続する」浮動小数点値の比率は均一ではありません。このアプローチでは、一部を見逃したり、xnext == x.

ある値から次に大きい値に移動するには、次のことを行う必要があります。

  • 仮数と指数を抽出します。
  • 仮数をインクリメントします。
  • オーバーフローした場合は、リセットして指数を増やします。
  • 指数と仮数から値を再構築します。

詳細は非常に面倒で、おそらく浮動小数点表現の知識が必要です。

ただし、IEEE と同様の表現を想定すると、ビット パターンを十分に大きな整数として再解釈し、その整数をインクリメントすることでこれを実現できます。これにより仮数がインクリメントされ、必要に応じてオーバーフローが指数に入ります。

于 2012-06-22T16:17:55.347 に答える