我需要一个简单的浮点舍入函数,这样:
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++库中,或者它是否丢失了??
当前回答
我在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
其他回答
它在cmath中从c++ 11开始提供(根据http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf)
#include <cmath>
#include <iostream>
int main(int argc, char** argv) {
std::cout << "round(0.5):\t" << round(0.5) << std::endl;
std::cout << "round(-0.5):\t" << round(-0.5) << std::endl;
std::cout << "round(1.4):\t" << round(1.4) << std::endl;
std::cout << "round(-1.4):\t" << round(-1.4) << std::endl;
std::cout << "round(1.6):\t" << round(1.6) << std::endl;
std::cout << "round(-1.6):\t" << round(-1.6) << std::endl;
return 0;
}
输出:
round(0.5): 1
round(-0.5): -1
round(1.4): 1
round(-1.4): -1
round(1.6): 2
round(-1.6): -2
它通常实现为下限(值+ 0.5)。
编辑:它可能不叫四舍五入,因为我知道至少有三种四舍五入算法:四舍五入到零,四舍五入到最接近的整数,以及银行家的四舍五入。你要求的是最接近的整数。
小心地板(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)的另一个原因。
如果您需要能够在支持c++ 11标准的环境中编译代码,但也需要能够在不支持c++ 11标准的环境中编译相同的代码,那么您可以使用函数宏在std::round()和每个系统的自定义函数之间进行选择。只需将-DCPP11或/DCPP11传递给兼容c++ 11的编译器(或使用其内置的版本宏),并创建一个像这样的头文件:
// File: rounding.h
#include <cmath>
#ifdef CPP11
#define ROUND(x) std::round(x)
#else /* CPP11 */
inline double myRound(double x) {
return (x >= 0.0 ? std::floor(x + 0.5) : std::ceil(x - 0.5));
}
#define ROUND(x) myRound(x)
#endif /* CPP11 */
有关快速示例,请参见http://ideone.com/zal709。
这在不兼容c++ 11的环境中近似于std::round(),包括保留-0.0的符号位。然而,这可能会导致轻微的性能损失,并且在舍入某些已知的“问题”浮点值(如0.4999999999999999994或类似值)时可能会出现问题。
或者,如果你有c++ 11兼容的编译器,你可以从它的<cmath>头文件中获取std::round(),并使用它来创建你自己的头文件来定义函数(如果它还没有定义的话)。但是请注意,这可能不是最佳解决方案,特别是如果您需要为多个平台编译时。
// Convert the float to a string
// We might use stringstream, but it looks like it truncates the float to only
//5 decimal points (maybe that's what you want anyway =P)
float MyFloat = 5.11133333311111333;
float NewConvertedFloat = 0.0;
string FirstString = " ";
string SecondString = " ";
stringstream ss (stringstream::in | stringstream::out);
ss << MyFloat;
FirstString = ss.str();
// Take out how ever many decimal places you want
// (this is a string it includes the point)
SecondString = FirstString.substr(0,5);
//whatever precision decimal place you want
// Convert it back to a float
stringstream(SecondString) >> NewConvertedFloat;
cout << NewConvertedFloat;
system("pause");
这可能是一种低效的肮脏的转换方式,但见鬼,它是有效的,哈哈。这很好,因为它适用于实际的浮点数。不仅仅是视觉上影响输出。