在std :: floor之后转换为int可以保证正确的结果吗?

时间:2009-03-03 08:21:22

标签: c++ math floor

我想要一个floor函数,其语法为

int floor(double x);

std::floor会返回double。是

static_cast <int> (std::floor(x));

保证给我正确的整数,还是我可以有一个一个一个的问题?它似乎有用,但我想肯定地知道。

对于奖励积分,为什么std::floor首先返回double

5 个答案:

答案 0 :(得分:28)

double的范围大于32或64位整数的范围,这就是std::floor返回double的原因。只要它在适当的范围内,转换为int应该没问题 - 但要注意double不能完全代表所有64位整数,所以当你走的时候也可能会出错超出double的准确性使得两个连续双打之间的差异大于1的点。

答案 1 :(得分:15)

static_cast <int> (std::floor(x));

几乎可以满足您的需求,是的。它给出了最接近的整数,舍入为-infinity。至少只要您的输入在int表示的范围内。 我不确定你的意思是'添加.5和诸如此类的东西,但它不会产生同样的效果

std :: floor返回一个双倍,因为这是最常见的。有时您可能想要舍入浮点数或双精度数,但保留类型。也就是说,围绕1.3f到1.0f,而不是1。

如果std :: floor返回一个int,那很难做到。 (或者至少你会有一些额外的不必要的演员放慢速度)。

如果floor只执行舍入本身,而不更改类型,则可以在需要时将其强制转换为int。

另一个原因是双打范围远远大于整数范围。可能无法将所有双打整数为整数。

答案 2 :(得分:7)

C ++标准说(4.9.1):

“浮点类型的rvalue可以转换为整数类型的rvalue。转换截断;也就是说,小数部分被丢弃。如果截断的值无法在目标类型中表示,则行为未定义”

因此,如果要将double转换为int,则数字在int范围内,并且所需的舍入值为零,那么只需将数字转换为int即可:

(INT)X;

答案 3 :(得分:5)

如果您想要处理各种数字条件并希望以受控方式处理不同类型的转换,那么您可能应该查看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;
}

答案 4 :(得分:2)

大多数标准数学库使用双精度数,但也提供浮点数。如果你不想使用双精度数,std :: floorf()是std :: floor()的单精度版本。

编辑:我删除了之前回答的部分内容。我曾经说过,当转换为int时,地板是多余的,但我忘了这只适用于正浮点数。