处理浮点数的精度问题
我想知道是否有办法克服精度问题,这似乎是我的机器内部表示浮点数的结果:
为了清楚起见,这个问题总结为:
// str is "4.600"; atof( str ) is 4.5999999999999996 double mw = atof( str ) // The variables used in the columns calculation below are: // // mw = 4.5999999999999996 // p = 0.2 // g = 0.2 // h = 1 (integer) int columns = (int) ( ( mw - ( h * 11 * p ) ) / ( ( h * 11 * p ) + g ) ) + 1;
在转换为整数types之前,列计算的结果是1.9999999999999996; 距离2.0的预期结果还有很远的距离。
任何build议最受欢迎。
将浮点数四舍五入为整数的非常简单而有效的方法:
int rounded = (int)(f + 0.5);
注意:这只适用于f
总是正数的情况。 (感谢j随机黑客)
当你使用浮点运算时,严格的相等几乎是毫无意义的。 您通常要比较一系列可接受的值。
请注意,某些值不能完全表示为浮点值。
看看每个计算机科学家应该知道的关于浮点算术和比较浮点数 。
如果你还没有阅读,那么这篇论文的标题是非常正确的。 请考虑阅读,了解更多关于现代计算机浮点运算的基础知识,一些陷阱,以及为什么他们的行为方式的解释。
没有准确的问题。
你得到的结果(1.9999999999999996)与math结果(2)的差别是1E-16。 这是相当准确的,考虑到你的input“4.600”。
当然,你有一个四舍五入的问题。 C ++中的缺省舍入是截断; 你想要类似于Kip的解决scheme。 细节取决于你的确切领域,你期望round(-x)== - round(x)
?
如果准确性真的很重要,那么你应该考虑使用双精度浮点数而不是浮点数。 虽然从你的问题看,你确实已经是。 但是,您在检查特定值时仍然有问题。 你需要代码(假设你正在检查你的值为零):
if (abs(value) < epsilon) { // Do Stuff }
其中“epsilon”是一些小的,但非零值。
在计算机上,浮点数从来都不是确切的。 它们只是一个近似的近似值。 (1e-16接近)
有时候有隐藏的东西你看不到 有时代数的基本规则不再适用:a * b!= b * a。 有时将寄存器与内存进行比较显示出这些微妙的差异。 或者使用math协处理器与运行时浮点库。 (我一直这样做太长了。)
C99定义:(查看math.h )
double round(double x); float roundf(float x); long double roundl(long double x);
。
或者你可以推出自己的:
template<class TYPE> inline int ROUND(const TYPE & x) { return int( (x > 0) ? (x + 0.5) : (x - 0.5) ); }
对于浮点等价,请尝试:
template<class TYPE> inline TYPE ABS(const TYPE & t) { return t>=0 ? t : - t; } template<class TYPE> inline bool FLOAT_EQUIVALENT( const TYPE & x, const TYPE & y, const TYPE & epsilon ) { return ABS(xy) < epsilon; }
你可以阅读这篇文章来find你正在寻找的东西。
你可以得到结果的绝对值,如下所示:
x = 0.2; y = 0.3; equal = (Math.abs(x - y) < 0.000001)
使用小数: decNumber ++