当前位置:  开发笔记 > 编程语言 > 正文

处理浮点数中的精度问题

如何解决《处理浮点数中的精度问题》经验,为你挑选了5个好方法。

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

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

// 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> kmkaplan..:

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

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

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



2> MSalters..:

没有遗嘱问题.

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

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



3> unwind..:

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



4> Kip..:

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

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

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


@Moshe:不必要是神秘的,但我认为它很可爱... :)如果`f`为正数或0,`(f <0)`为`0`,则整个表达式像以前一样计算为`0.5`,因此正数舍入不受影响;但是如果`f`为负数,则(f <0)的取值为'1',然后将其从`0.5`减去以得到`-0.5`,这也会导致负数也四舍五入到最接近的值。
@Moshe:不确定abs()会给您带来很多好处,因为大概您希望最终答案具有原始符号,这意味着您需要通过乘以原始符号来“反转” abs()。仅仅将`0.5`替换为`(0.5-(f <0))`可能更简单。

5> ChrisF..:

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

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

其中"epsilon"是一些小但非零的值.


我认为你的意思是"abs(computed_value - expected_value)
推荐阅读
pan2502851807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有