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

Jes*_*der 38 c++ math floor

我想要一个floor带语法的函数

int floor(double x);
Run Code Online (Sandbox Code Playgroud)

但是std::floor返回一个double.是

static_cast <int> (std::floor(x));
Run Code Online (Sandbox Code Playgroud)

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

对于奖励积分,为什么heck确实在第一时间std::floor返回double

Jon*_*eet 28

double的范围大于32位或64位整数的范围,这就是为什么std::floor返回a double.铸造到int应该罚款,只要它是在适当的范围内-但要知道,一个double不能代表所有的64位整数准确,所以你也可以结束了错误,当你超越在其精度的点double是这样的两个连续双打之间的差异大于1.

  • Floor 如何返回非精确整数的值?对于小双精度数(epsilon &lt;&lt; 1),可以表示所有整数值,包括下限(x)。对于大双精度数(epsilon &gt;&gt; 1),只能表示整数值,因此floor(x)==x。 (3认同)
  • 所以如果它在正确的范围内,演员阵容就可以了吗?它在规范中在哪里说(暗示)这一点? (2认同)

jal*_*alf 16

static_cast <int> (std::floor(x));
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

另一个原因是双打范围远远大于整数范围.可能无法将所有双打四舍五入到整数.


Mic*_*bon 7

C++标准说(4.9.1):

"浮点类型的右值可以被转换为整数类型的右值转换截断;即,小数部分被丢弃,则行为未定义如果截断值不能在目标类型来表示".

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

(INT)X;

  • 我已经清楚地写了“所以如果......所需的四舍五入是向零”以区分这种情况与“向无穷大四舍五入”。Floor 向-无穷大舍入,截断-向零。 (2认同)

Ano*_*ous 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;
}
Run Code Online (Sandbox Code Playgroud)