boostfloating-pointcomparedecimalmultiprecision

Boost muliprecision cpp_dec_float compare only to desired precision


I am using the boost::multiprecision library for decimal float types, and wish to compare two floats to the specified precision.

However, cpp_dec_float seems to compare the number not to the specified precision, but also includes the guard digits:

#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;
}

Output:

1.4142135623730950488016887242096980785696718753769
1.4142135623730950488016887242096980785696718753769
0

Expected:

1.4142135623730950488016887242096980785696718753769
1.4142135623730950488016887242096980785696718753769
1

See on Coliru

I have tried to "truncate" with precision(), but to no avail. Is there a way to compare the two numbers without resorting to epsilon comparisons?


Solution

  • If you strip the guard bits, you effectively cripple the fidelity of the type as intended.

    A surefire way would be to use (de)serialization, really.

    So I suggest

    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;
    

    Note that the epsilon is 1e-49 there

    Prints

    1.4142135623730950488016887242096980785696718753769
    1.4142135623730950488016887242096980785696718753769
    1e-49
    1
    1
    

    Obviously the epsilon() based comparison would be appear the more efficient