我很怀疑这些函数之一可能会给出这样的错误结果:
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”返回类型。)
最佳答案
人们通常认为浮点运算产生的结果带有小的、不可预测的、准随机错误。此印象不正确。
浮点算术计算尽可能精确。 18/3
将始终产生 正好 6。 1/3
的结果不会正好是三分之一,但它会是最接近三分之一的可表示为 float 的数字。
因此,您展示的示例保证始终有效。至于您建议的“保证地板/天花板”,这不是一个好主意。某些操作序列很容易将错误排除在 1e-10
之上,而某些其他用例将要求 1e-10
被正确识别(和上限)为非零。
根据经验,硬编码的 epsilon 值是代码中的错误。
关于c++ - 将 `std::floor()` 和 `std::ceil()` 转换为整数类型是否总是给出正确的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34996987/