我想要一个floor
具有语法的函数
int floor(double x);
但std::floor
返回一个double
. 是
static_cast <int> (std::floor(x));
保证给我正确的整数,还是我有一个不合一的问题?它似乎有效,但我想确定。
对于奖励积分,为什么首先std::floor
返回 adouble
呢?
double 的范围远大于 32 或 64 位整数的范围,这就是std::floor
返回 a 的原因double
。int
只要它在适当的范围内,转换为就应该没问题 - 但请注意,adouble
不能准确地表示所有 64 位整数,因此当您超出精确度的点时,您也可能会出现double
错误连续两次双打之差大于1。
static_cast <int> (std::floor(x));
几乎可以满足您的需求,是的。它为您提供最接近的整数,向 -infinity 四舍五入。至少只要您的输入在整数可表示的范围内。我不确定'添加 .5 之类的东西是什么意思,但它不会产生相同的效果
std::floor 返回一个双精度值,因为这是最通用的。有时您可能希望对浮点数或双精度数进行四舍五入,但保留类型。也就是说,将 1.3f 舍入到 1.0f,而不是 1。
如果 std::floor 返回一个 int,那将很难做到。(或者至少你会有额外的不必要的演员在那里减慢速度)。
如果 floor 仅执行舍入本身,而不更改类型,则可以在需要时将其转换为 int 。
另一个原因是双精度数的范围远大于整数。可能无法将所有双精度数舍入为整数。
C++ 标准说(4.9.1):
“浮点类型的右值可以转换为整数类型的右值。转换截断;也就是说,小数部分被丢弃。如果截断的值不能在目标类型中表示,则行为未定义”。
因此,如果要将 double 转换为 int,则该数字在 int 范围内,并且所需的向上舍入为零,那么只需将数字转换为 int 就足够了:
(int)x;
如果您想处理各种数字条件并希望以受控方式处理不同类型的转换,那么也许您应该查看Boost.NumericConversion。这个库允许处理奇怪的情况(如超出范围、舍入、范围等)
这是文档中的示例:
#include <cassert>
#include <boost/numeric/conversion/converter.hpp>
int main() {
typedef boost::numeric::converter<int,double> Double2Int ;
int x = Double2Int::convert(2.0);
assert ( x == 2 );
int y = Double2Int()(3.14); // As a function object.
assert ( y == 3 ) ; // The default rounding is trunc.
try
{
double m = boost::numeric::bounds<double>::highest();
int z = Double2Int::convert(m); // By default throws positive_overflow()
}
catch ( boost::numeric::positive_overflow const& )
{
}
return 0;
}
大多数标准数学库使用双精度,但也提供浮点版本。如果您不想使用双精度数,则 std::floorf() 是 std::floor() 的单精度版本。
编辑:我已经删除了我之前答案的一部分。我曾说过在转换为 int 时地板是多余的,但我忘记了这仅适用于正浮点数。