Я параною, что одна из этих функций может дать неверный результат, например:
std::floor(2000.0 / 1000.0) --> std::floor(1.999999999999) --> 1
or
std::ceil(18 / 3) --> std::ceil(6.000000000001) --> 7
Может ли такое случиться? Если такой риск действительно существует, я планирую использовать перечисленные ниже функции для безопасной работы. Но действительно ли это необходимо?
constexpr long double EPSILON = 1e-10;
intmax_t GuaranteedFloor(const long double & Number)
{
if (Number > 0)
{
return static_cast<intmax_t>(std::floor(Number) + EPSILON);
}
else
{
return static_cast<intmax_t>(std::floor(Number) - EPSILON);
}
}
intmax_t GuaranteedCeil(const long double & Number)
{
if (Number > 0)
{
return static_cast<intmax_t>(std::ceil(Number) + EPSILON);
}
else
{
return static_cast<intmax_t>(std::ceil(Number) - EPSILON);
}
}
(Примечание: я предполагаю, что данный аргумент 'long double' будет соответствовать типу возвращаемого значения 'intmax_t'.)
EPSILON
тебя не спасет. Это наименьшая значимая разница при 1,0, то есть наименьшее значение, которое вы можете добавить к 1,0, чтобы получить другое значение. Если ваш результат может быть больше или меньше 1.0, вам понадобится другойEPSILON
. Если вы думаете, что вам нужноEPSILON
для чего-нибудь, скорее всего, вы собираетесь внести в свое программное обеспечение очень тонкую ошибку. - person DevSolar   schedule 25.01.2016static_cast
вы можете рассмотретьstd::lround
, который возвращает ближайшее целое число:int i = std::lround(std::ceil(f))
. Это избавит от необходимости использовать эпсилон или условные выражения. - person Jonathan Lidbeck   schedule 20.07.2018