Мне нужна функция защиты от переполнения , которая округляет double
, как std::round
, кроме того, она может обрабатывать количество значащих десятичных разрядов.
fe
round(-17.747, 2) -> -17.75
round(-9.97729, 2) -> -9.98
round(-5.62448, 2) -> -5.62
round(std::numeric_limits<double>::max(), 10) ...
Моя первая попытка была
double round(double value, int precision)
{
double factor=pow(10.0, precision);
return floor(value*factor+0.5)/factor;
}
, но это может легко переполнить.
Предполагая IEEE, можно уменьшить вероятность переполнения, как это.
double round(double value, int precision)
{
// assuming IEEE 754 with 64 bit representation
// the number of significant digits varies between 15 and 17
precision=std::min(17, precision);
double factor=pow(10.0, precision);
return floor(value*factor+0.5)/factor;
}
Но это все еще может переполниться.
Даже эта катастрофа производительности не работает.
double round(double value, int precision)
{
std::stringstream ss;
ss << std::setprecision(precision) << value;
std::string::size_type sz;
return std::stod(ss.str(), &sz);
}
round(std::numeric_limits<double>::max(), 2.0) // throws std::out_of_range
Примечание :
- Я знаю о
setprecision
, но мне нужно округлить не только для отображения цели. Так что это не решение. - В отличие от этого поста Как округлить число до n десятичных знаков в Java, мой вопрос особенно о безопасности переполнения и в C ++ (ответчик в топиках c выше Java -specifi c или не обрабатываются переполнения)