2

10 進数の float 型に boost::multiprecision ライブラリを使用しており、2 つの float を指定された精度と比較したいと考えています。

ただし、 cpp_dec_float は数値を指定された精度と比較していないようですが、ガード桁も含まれています。

#include <iostream>

#include <boost/multiprecision/cpp_dec_float.hpp>
//#include <boost/math/special_functions.hpp>

typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50> > flp_type;

int main(int argc, char* argv[])
{
    // 50 decimal digits
    flp_type sqrt2("1.4142135623730950488016887242096980785696718753769");
    // Contains calculated guard digits
    flp_type result(boost::multiprecision::sqrt(flp_type("2")));

    // The 50 digits of precision actually ompare equal
    std::cout << std::setprecision(50) << sqrt2 << std::endl;
    std::cout << std::setprecision(50) << result << std::endl;
    // I want this to compare to the specified precision of the type, not the guard digits
    std::cout << (result==sqrt2) << std::endl;

    return 0;
}

出力:

1.4142135623730950488016887242096980785696718753769
1.4142135623730950488016887242096980785696718753769
0

期待される:

1.4142135623730950488016887242096980785696718753769
1.4142135623730950488016887242096980785696718753769
1

コリルで見る

precision() で「切り詰め」ようとしましたが、役に立ちませんでした。イプシロン比較に頼らずに 2 つの数値を比較する方法はありますか?

4

2 に答える 2

2

ガード ビットを削除すると、意図した型の忠実度が効果的に損なわれます。

確かな方法は、実際には(逆)シリアル化を使用することです。

だから私は提案します

Live On Coliru

// Either
std::cout << std::numeric_limits<flp_type>::epsilon() << "\n";
std::cout << (abs(result-sqrt2) < std::numeric_limits<flp_type>::epsilon()) << std::endl;

// Or
result = flp_type { result.str(49, std::ios::fixed) };
std::cout << (result==sqrt2) << std::endl;

イプシロンが1e-49あることに注意してください

版画

1.4142135623730950488016887242096980785696718753769
1.4142135623730950488016887242096980785696718753769
1e-49
1
1

明らかに、epsilon()ベースの比較はより効率的であるように見えます

于 2014-12-09T14:55:53.447 に答える
0
bool is_equal = abs(result-sqrt2) < std::pow(10, -std::numeric_limits< flp_type >::digits10 );
于 2021-01-09T04:28:26.017 に答える