我需要一个简单的浮点舍入函数,这样:
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++库中,或者它是否丢失了??
当前回答
Boost中还实现了某种类型的舍入:
#include <iostream>
#include <boost/numeric/conversion/converter.hpp>
template<typename T, typename S> T round2(const S& x) {
typedef boost::numeric::conversion_traits<T, S> Traits;
typedef boost::numeric::def_overflow_handler OverflowHandler;
typedef boost::numeric::RoundEven<typename Traits::source_type> Rounder;
typedef boost::numeric::converter<T, S, Traits, OverflowHandler, Rounder> Converter;
return Converter::convert(x);
}
int main() {
std::cout << round2<int, double>(0.1) << ' ' << round2<int, double>(-0.1) << ' ' << round2<int, double>(-0.9) << std::endl;
}
注意,这仅在执行到整数的转换时有效。
其他回答
我是这样做的:
#include <cmath.h>
using namespace std;
double roundh(double number, int place){
/* place = decimal point. Putting in 0 will make it round to whole
number. putting in 1 will round to the
tenths digit.
*/
number *= 10^place;
int istack = (int)floor(number);
int out = number-istack;
if (out < 0.5){
floor(number);
number /= 10^place;
return number;
}
if (out > 0.4) {
ceil(number);
number /= 10^place;
return number;
}
}
Boost中还实现了某种类型的舍入:
#include <iostream>
#include <boost/numeric/conversion/converter.hpp>
template<typename T, typename S> T round2(const S& x) {
typedef boost::numeric::conversion_traits<T, S> Traits;
typedef boost::numeric::def_overflow_handler OverflowHandler;
typedef boost::numeric::RoundEven<typename Traits::source_type> Rounder;
typedef boost::numeric::converter<T, S, Traits, OverflowHandler, Rounder> Converter;
return Converter::convert(x);
}
int main() {
std::cout << round2<int, double>(0.1) << ' ' << round2<int, double>(-0.1) << ' ' << round2<int, double>(-0.9) << std::endl;
}
注意,这仅在执行到整数的转换时有效。
Boost提供了一组简单的舍入函数。
#include <boost/math/special_functions/round.hpp>
double a = boost::math::round(1.5); // Yields 2.0
int b = boost::math::iround(1.5); // Yields 2 as an integer
有关更多信息,请参阅Boost文档。
编辑:从c++ 11开始,有std::round, std::lround和std::llround。
我在asm的x86架构和MS VS特定的c++中使用round的以下实现:
__forceinline int Round(const double v)
{
int r;
__asm
{
FLD v
FISTP r
FWAIT
};
return r;
}
UPD:返回双值
__forceinline double dround(const double v)
{
double r;
__asm
{
FLD v
FRNDINT
FSTP r
FWAIT
};
return r;
}
输出:
dround(0.1): 0.000000000000000
dround(-0.1): -0.000000000000000
dround(0.9): 1.000000000000000
dround(-0.9): -1.000000000000000
dround(1.1): 1.000000000000000
dround(-1.1): -1.000000000000000
dround(0.49999999999999994): 0.000000000000000
dround(-0.49999999999999994): -0.000000000000000
dround(0.5): 0.000000000000000
dround(-0.5): -0.000000000000000
小心地板(x+0.5)。下面是在[2^52,2^53]范围内奇数的情况:
-bash-3.2$ cat >test-round.c <<END
#include <math.h>
#include <stdio.h>
int main() {
double x=5000000000000001.0;
double y=round(x);
double z=floor(x+0.5);
printf(" x =%f\n",x);
printf("round(x) =%f\n",y);
printf("floor(x+0.5)=%f\n",z);
return 0;
}
END
-bash-3.2$ gcc test-round.c
-bash-3.2$ ./a.out
x =5000000000000001.000000
round(x) =5000000000000001.000000
floor(x+0.5)=5000000000000002.000000
这里是http://bugs.squeak.org/view.php?id=7134。使用@konik这样的解决方案。
我自己的健壮版本是这样的:
double round(double x)
{
double truncated,roundedFraction;
double fraction = modf(x, &truncated);
modf(2.0*fraction, &roundedFraction);
return truncated + roundedFraction;
}
这里给出了避免下限(x+0.5)的另一个原因。