我需要一个简单的浮点舍入函数,这样:
double round(double);
round(0.1) = 0
round(-0.1) = 0
round(-0.9) = -1
我可以在math.h中找到ceil()和floor() -但没有round()。
它是否以另一个名字出现在标准c++库中,或者它是否丢失了??
我需要一个简单的浮点舍入函数,这样:
double round(double);
round(0.1) = 0
round(-0.1) = 0
round(-0.9) = -1
我可以在math.h中找到ceil()和floor() -但没有round()。
它是否以另一个名字出现在标准c++库中,或者它是否丢失了??
当前回答
round_f for ARM with math
static inline float round_f(float value)
{
float rep;
asm volatile ("vrinta.f32 %0,%1" : "=t"(rep) : "t"(value));
return rep;
}
没有数学的ARM的round_f
union f__raw {
struct {
uint32_t massa :23;
uint32_t order :8;
uint32_t sign :1;
};
int32_t i_raw;
float f_raw;
};
float round_f(float value)
{
union f__raw raw;
int32_t exx;
uint32_t ex_mask;
raw.f_raw = value;
exx = raw.order - 126;
if (exx < 0) {
raw.i_raw &= 0x80000000;
} else if (exx < 24) {
ex_mask = 0x00ffffff >> exx;
raw.i_raw += 0x00800000 >> exx;
if (exx == 0) ex_mask >>= 1;
raw.i_raw &= ~ex_mask;
};
return raw.f_raw;
};
其他回答
它通常实现为下限(值+ 0.5)。
编辑:它可能不叫四舍五入,因为我知道至少有三种四舍五入算法:四舍五入到零,四舍五入到最接近的整数,以及银行家的四舍五入。你要求的是最接近的整数。
round_f for ARM with math
static inline float round_f(float value)
{
float rep;
asm volatile ("vrinta.f32 %0,%1" : "=t"(rep) : "t"(value));
return rep;
}
没有数学的ARM的round_f
union f__raw {
struct {
uint32_t massa :23;
uint32_t order :8;
uint32_t sign :1;
};
int32_t i_raw;
float f_raw;
};
float round_f(float value)
{
union f__raw raw;
int32_t exx;
uint32_t ex_mask;
raw.f_raw = value;
exx = raw.order - 126;
if (exx < 0) {
raw.i_raw &= 0x80000000;
} else if (exx < 24) {
ex_mask = 0x00ffffff >> exx;
raw.i_raw += 0x00800000 >> exx;
if (exx == 0) ex_mask >>= 1;
raw.i_raw &= ~ex_mask;
};
return raw.f_raw;
};
从c++ 11开始简单地:
#include <cmath>
std::round(1.1)
或者得到int
static_cast<int>(std::round(1.1))
c++ 03标准依赖于C90标准,该标准称为标准C库,该标准在c++ 03标准草案中涵盖(最接近c++ 03的公开标准草案是N1804) 1.2节规范参考:
ISO/IEC 9899:1990第7条和ISO/IEC 9899:1990第7条描述的库 ISO / IEC 9899 / Amd。1:1995以下称为标准C Library.1)
如果我们去cppreference上的round, lround, llround的C文档,我们可以看到round和相关函数是C99的一部分,因此在c++ 03或更早的版本中不可用。
在c++ 11中,这种情况发生了变化,因为c++ 11依赖于C标准库的C99草案标准,因此提供了std::round和for整型返回类型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, round, 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节浮动积分转换中看到这一点,其中说(强调我的):
浮点类型的右值可以转换为类的右值 整数类型。转换截断;也就是小数部分 就会被丢弃。如果截断的值不能,则行为未定义 用目标类型表示。[…]
例如:
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可能是一个选择,因为它是一个经过良好测试的实现。
将浮点值四舍五入小数“n”位的最佳方法如下,在O(1)时间内:-
我们必须将值四舍五入3位,即n=3。所以,
float a=47.8732355;
printf("%.3f",a);