Простые альтернативы с плавающей точкой при выполнении арифметики на рациональных кодировках с короткой строкой

Я создаю модульные тесты для функции, которая округляет «рациональные» числа, хранящиеся в виде строк. Текущая реализация округления приводит строки к типу с плавающей запятой:

#include <boost/lexical_cast.hpp>

#include <iomanip>
#include <limits>
#include <sstream>

template<typename T = double,
size_t PRECISION = std::numeric_limits<T>::digits10>
std::string Round(const std::string& number)
{
std::stringstream ss{};
ss << std::fixed << std::setprecision(PRECISION);
ss << boost::lexical_cast<T>(number);
return ss.str();
}

В одном из моих тестов я ввел число 3.55, которое представлено как 3.5499999 … на моей машине. Все идет хорошо при округлении с 2 десятичных знаков до 10. Однако, когда я округляю до первого десятичного знака, я неудивительно, что получаю 3,5 вместо 3,6.

Какой простой способ избежать этой ошибки?

В настоящее время лучшее решение, которое мне удалось найти, — это использовать тип с множественной точностью:

#include <boost/multiprecision/cpp_dec_float.hpp>

#include <iomanip>
#include <sstream>

template<size_t PRECISION = 10>
std::string Round(const std::string& number)
{
using FixedPrecision =
boost::multiprecision::number<
boost::multiprecision::cpp_dec_float<PRECISION>>;

std::stringstream ss{};
ss << std::fixed << std::setprecision(PRECISION);
ss << FixedPrecision{number};
return ss.str();
}

Хотя это решение решает проблему простым способом (по сравнению с ручным синтаксическим анализом строк или созданием класса чисел Rational), я считаю его излишним для такой простой проблемы.

Чтобы найти способы решения этой проблемы, я заглянул в некоторые реализации калькуляторов. Я посмотрел на исходный код gnome-calculator и обнаружил, что он использует GNU MPFR. Затем я посмотрел на реализацию SpeedCrunch и обнаружил, что он повторно использует тот же код, что и bc, который использует рациональный тип (числитель, знаменатель).

Я что-то пропускаю?

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]