4

float、、タイプの)浮動小数点数で操作する場合、精度の低下を検出することは可能ですか?言う:doublelong double

template< typename F >
F const sum(F const & a, F const & b)
{
    F const sum_(a + b);
    // The loss of precision must be detected (here or one line above) if some fraction bit is lost due to rounding
    return sum_;
}

x87 FPUがターゲットアーキテクチャに存在するがasm、純粋なC++コードへのルーチンの介入がない場合に特に関心があります。C++11またはgnu++11固有の機能も受け入れられます。

4

4 に答える 4

4

C ++標準は、浮動小数点精度の概念について非常にあいまいです。精度の低下を検出するための完全に標準に準拠した方法はありません。

GNUは、浮動小数点例外を有効にする拡張機能を提供します。トラップしたい例外はですFE_INEXACT

于 2013-01-19T21:02:55.943 に答える
1

Boostライブラリで区間演算を使用することを検討してください。計算中に区間の誤差が常に増加するという特性を保証できます∀ x ∈[a,b], f(x) ∈ f([a,b])

あなたの場合、[a-EPS,a+EPS]最初の数に最初の範囲を使用することを検討するかもしれませんa。一連の操作の後、abs(y-x)結果の間隔[x,y]は、知りたい精度の(最大の)損失になります。

于 2013-01-19T21:18:40.213 に答える
1

あなたを助ける1つのことはstd::numeric_limits<double>::epsilon、「1と表現可能な1より大きい最小値との差」を返すことです。言い換えると、1と評価される最大のx>0を示します。1+x

于 2013-01-19T21:11:44.170 に答える
1

次のようなものを使用できます。

#include <iostream>
#include <fenv.h>

#pragma STDC FENV_ACCESS ON

template <typename F> F sum (const F a, const F b, F &error) {
    int round = fegetround();

    fesetround(FE_TONEAREST);
    F c = a + b;

    fesetround(FE_DOWNWARD);
    F c_lo = a + b;

    fesetround(FE_UPWARD);
    F c_hi = a + b;

    fesetround(FE_TONEAREST);
    error = std::max((c - c_lo), (c_hi - c));

    fesetround(round);

    return c;
}


int main() {
    float a = 23.23528;
    float b = 4.234;
    float e;

    std::cout << sum(a, b, e) << std::endl;
    std::cout << e << std::endl;
}

最大エラー量の簡単な見積もりがerror引数に返されます。丸めモードを切り替えると、浮動小数点ユニット(FPU)パイプラインがフラッシュされるため、非常に高速な速度を期待しないでください。

より良い解決策は、区間演算(変数の相関が考慮されていないため、悲観的な誤差間隔を与える傾向がある)、またはアフィン演算(変数の相関を追跡し、したがって、いくらか厳しい誤差範囲を与える)を試すことです。

これらの方法の入門書については、こちらをお読みください: http ://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.36.8089

于 2016-03-16T18:44:15.633 に答える