2010-08-05 130 views
10

http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/ 我已经了解这个最近审查C++。避免舍入误差(具体地浮动)C++

在一般的计算课堂教授往往不会涵盖这些小事情,虽然我们知道舍入误差意味着什么。

有人可以帮助我如何避免舍入误差?

该教程显示了一个示例代码

#include <iomanip> 
int main() 
{ 
    using namespace std; 
    cout << setprecision(17); 
    double dValue = 0.1; 
    cout << dValue << endl; 
} 

此输出

0.10000000000000001

默认浮子保持精度的6位数字。因此,当我们重写默认值,并要求更多(在这种情况下,17 !!),我们可能会遇到截断(正如教程中所解释的那样)。 对于双,最高的是16

在一般情况下,如何做好C++程序员避免舍入误差? 你们一直在看数字的二进制表示吗?

谢谢。

+3

设置精度流格式化代码使用 - 与数字的表示方式无关,或在其他代码中使用。 – 2010-08-05 23:45:40

回答

0

大多数浮点输出程序看看如果答案是非常接近的时候在基地10轮的答案实际上是即使在输出表示是偶数。通过这种方式设置精度,可以使这个过程短路。

这个舍入是完成的,因为甚至在基数10中出现的答案几乎都不会在基数2(即在内部表示数字的基数)中是偶数(即结束于无限长的尾部0的串)。但是,当然,输出程序的总体目标是呈现数量的方式有用的一个人,和世界上大多数人在今天阅读基地数量10

0

短版 - 你可以”当你试图以基数2表示基数为10的数字(即,使用浮点数或双精度数来表示小数)时,真的避免舍入和其他表示错误。你几乎不得不计算你实际有多少有效数字,或者你必须切换到一个(较慢)的任意精度库。

0

换句话说,尽量减少舍入误差,它可以帮助保持数十进制定点(实际上与整数工作)。

#include <iostream> 
#include <iomanip> 

int main() { 

    using namespace std; 

    cout << setprecision(17); 

    double v1=1, v1D=10; 
    cout << v1/v1D << endl; // 0.10000000000000001 


    double v2=3, v2D=1000; //0.0030000000000000001 
    cout << v2/v2D << endl; 

    // v1/v1D + v2/v2D = (v1*v2D+v2*v1D)/(v1D*v2D) 

    cout << (v1*v2D+v2*v1D)/(v1D*v2D) << endl; // 0.10299999999999999 

} 
0

你想用所谓的“固定”,所以他们做一个科学记数法不圆或显示以正确格式的数字操纵你使用固定后,您还可以使用设置精度()函数设置值的位置在右侧。 小数点。该示例将如下使用您的原始代码。

#include <iostream> 
#include <iomanip> 
    int main() { 
      using namespace std; 
      #include <iomanip> 


    double dValue = 0.19213; 
    cout << fixed << setprecision(2) << dValue << endl 


     } 

输出为:

dValue = 0.19 
0

当你计算方差一样,你可以有这样的问题,简单的事情......这是我的解决方案...

int getValue(double val, int precision){ 
std::stringstream ss; 
ss << val; 
string strVal = ss.str(); 
size_t start = strVal.find("."); 

std::string major = strVal.substr(0, start); 
std::string minor = strVal.substr(start + 1); 

// Fill whit zero... 
while(minor.length() < precision){ 
    minor += "0"; 
} 

// Trim over precision... 
if(minor.length() > precision){ 
    minor = minor.substr(0, precision); 
} 

strVal = major + minor; 
int intVal = atoi(strVal.c_str()); 

return intVal; 
} 

所以你将使您的calcul在整数范围内... 例如2523.49变成了252349白色精确度的两位数字,并且2523490白色精度为树数字......如果您计算平均值,例如第一个y ou转换所有的值在整数,使求和得到双倍的结果,所以你不积累错误...错误是像平方根和功率函数放大白衣操作...