繁体   English   中英

处理浮点数中的精度问题

[英]Dealing with accuracy problems in floating-point numbers

我想知道是否有办法克服精确度问题,这似乎是我的机器内部表示浮点数的结果:

为清楚起见,问题归纳为:

// 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;

在转换为整数类型之前,列计算的结果是1.9999999999999996; 距离2.0的理想结果还差不多。

任何建议最受欢迎。

当你使用浮点运算时,严格的相等几乎毫无意义。 您通常希望与一系列可接受的值进行比较。

请注意,某些值不能完全表示为浮点线索。

了解每个计算机科学家应该知道的关于浮点运算比较浮点数的内容

没有遗嘱问题。

您获得的结果(1.9999999999999996)与数学结果(2)的差异为1E-16。 考虑到您的输入“4.600”,这非常准确。

当然,你确实有一个舍入问题。 C ++中的默认舍入是截断; 你想要类似于Kip的解决方案。 详细信息取决于您的确切域名,您期望round(-x)== - round(x)

如果您还没有阅读,那么本文的标题就是正确的。 请考虑阅读它,了解更多关于现代计算机上浮点运算的基本原理,一些陷阱,以及解释为什么它们的行为方式。

如果准确性非常重要,那么您应该考虑使用双精度浮点数而不仅仅是浮点数。 虽然从你的问题来看,它确实看起来你已经是。 但是,检查特定值时仍然存在问题。 你需要代码(假设你正在检查你的值为零):

if (abs(value) < epsilon)
{
   // Do Stuff
}

其中“epsilon”是一些小但非零的值。

将浮点数舍入为整数的一种非常简单有效的方法:

int rounded = (int)(f + 0.5);

注意:这仅在f始终为正时才有效。 (谢谢j随机黑客​​)

在计算机上,浮点数永远不会精确。 它们总是非常接近。 (1e-16很接近。)

有时候你看不到隐藏的部分。 有时候代数的基本规则不再适用:a * b!= b * a。 有时将寄存器与存储器进行比较会显示出这些微妙的差异。 或者使用数学协处理器与运行时浮点库。 (我一直在做这件事太长了。)

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(x-y) < epsilon; }

使用小数: decNumber ++

您可以阅读本文以找到您要找的内容。

你可以得到结果的绝对值看到这里

x = 0.2;  
y = 0.3;  
equal = (Math.abs(x - y) < 0.000001)  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM