C ++ 03标准依赖于C90标准,该标准称为标准C库,C ++ 03标准草案中涵盖了该标准C库(与C ++ 03 最接近的公开可用标准草案是N1804)部分1.2
规范性引用:
ISO / IEC 9899:1990第7条和ISO / IEC 9899 / Amd.1:1995第7条中描述的库在下文中称为标准C库。1)
如果转到cppreference上的round,lround,llround的C文档,我们可以看到round和相关函数是C99的一部分,因此在C ++ 03或更早的版本中将不可用。
在C ++ 11中,这发生了变化,因为C ++ 11依赖于C标准库的C99草案标准,因此提供了std :: round和整数返回类型std :: lround,std :: llround:
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::round( 0.4 ) << " " << std::lround( 0.4 ) << " " << std::llround( 0.4 ) << std::endl ;
std::cout << std::round( 0.5 ) << " " << std::lround( 0.5 ) << " " << std::llround( 0.5 ) << std::endl ;
std::cout << std::round( 0.6 ) << " " << std::lround( 0.6 ) << " " << std::llround( 0.6 ) << std::endl ;
}
同样来自C99的另一种选择是std :: trunc,其中:
计算幅度不大于arg的最接近整数。
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::trunc( 0.4 ) << std::endl ;
std::cout << std::trunc( 0.9 ) << std::endl ;
std::cout << std::trunc( 1.1 ) << std::endl ;
}
如果您需要支持非C ++ 11应用程序,那么最好的选择是使用boost round,iround,lround,llround或boost trunc。
推出自己的版本回合很难
滚动自己可能不值得,因为比看起来更难:将浮点数四舍五入到最接近的整数,第1部分,将浮点数四舍五入到最接近的整数,第2部分以及将浮点数四舍五入到最近的整数,第3部分说明:
例如,使用std::floor
和添加实现的通用清单0.5
不适用于所有输入:
double myround(double d)
{
return std::floor(d + 0.5);
}
此输入将失败的一个输入是0.49999999999999994
,(请实时查看)。
另一种常见的实现方式涉及将浮点类型转换为整数类型,如果整数部分无法用目标类型表示,则可以调用未定义的行为。我们可以从C ++标准草案的4.9
浮点整数转换部分看到这一点,其中说:强调我的):
浮点类型的prvalue可以转换为整数类型的prvalue。转换被截断;即,小数部分被丢弃。如果无法在目标类型中表示截断的值,则该行为是不确定的。[...]
例如:
float myround(float f)
{
return static_cast<float>( static_cast<unsigned int>( f ) ) ;
}
给定std::numeric_limits<unsigned int>::max()
是4294967295
那么下面的电话:
myround( 4294967296.5f )
会导致溢出,(请参阅实况)。
通过查看在C中实现round()的简洁方法的答案,我们可以看出这到底有多困难?引用新库版本的单精度浮点舍入。对于看起来很简单的东西,这是一个非常长的功能。不太了解浮点实现的人似乎不可能正确实现此功能:
float roundf(x)
{
int signbit;
__uint32_t w;
/* Most significant word, least significant word. */
int exponent_less_127;
GET_FLOAT_WORD(w, x);
/* Extract sign bit. */
signbit = w & 0x80000000;
/* Extract exponent field. */
exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;
if (exponent_less_127 < 23)
{
if (exponent_less_127 < 0)
{
w &= 0x80000000;
if (exponent_less_127 == -1)
/* Result is +1.0 or -1.0. */
w |= ((__uint32_t)127 << 23);
}
else
{
unsigned int exponent_mask = 0x007fffff >> exponent_less_127;
if ((w & exponent_mask) == 0)
/* x has an integral value. */
return x;
w += 0x00400000 >> exponent_less_127;
w &= ~exponent_mask;
}
}
else
{
if (exponent_less_127 == 128)
/* x is NaN or infinite. */
return x + x;
else
return x;
}
SET_FLOAT_WORD(x, w);
return x;
}
另一方面,如果没有其他解决方案可用,则newlib可能是一个选择,因为它是经过良好测试的实现。
std::cout << std::fixed << std::setprecision(0) << -0.9
。