Увеличьте мультипрецизионное сравнение cpp_dec_float только до желаемой точности
Я использую библиотеку boost:: multiprecision для десятичных типов с плавающей запятой и хочу сравнить два числа с заданной точностью.
Однако, 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
Я пытался "усечь" с точностью (), но безрезультатно. Есть ли способ сравнить два числа, не прибегая к эпсилон-сравнениям?
2 ответа
Решение
Если вы снимаете защитные биты, вы фактически наносите вред точности воспроизведения типа, как и предполагалось.
Верным способом было бы использовать (де) сериализацию, действительно.
Поэтому я предлагаю
// 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()
сравнение будет казаться более эффективным
bool is_equal = abs(result-sqrt2) < std::pow(10, -std::numeric_limits< flp_type >::digits10 );