avoid rounding error (floating specifically) c++

前端 未结 6 1546
耶瑟儿~
耶瑟儿~ 2021-02-04 12:54

http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/ I have been about this lately to review C++.

In general computing class professors tend not to cover thes

相关标签:
6条回答
  • 2021-02-04 13:26

    Short version - you can't really avoid rounding and other representation errors when you're trying to represent base 10 numbers in base 2 (ie, using a float or a double to represent a decimal number). You pretty much either have to work out how many significant digits you actually have or you have to switch to a (slower) arbitrary precision library.

    0 讨论(0)
  • 2021-02-04 13:34

    In other words, to minimize rounding errors, it can be helpful to keep numbers in decimal fixed-point (and actually work with integers).

    #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 讨论(0)
  • 2021-02-04 13:37

    The canonical advice for this topic is to read "What Every Computer Scientist Should Know About Floating-Point Arithmetic", by David Goldberg.

    0 讨论(0)
  • 2021-02-04 13:38

    When you calculate simple thing like variance you can have this kind of problem... here is my solution...

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

    So you will make your calcul in the integer range... for example 2523.49 became 252349 whit a precision of tow digits, and 2523490 whit a precision of tree digit... if you calculate the mean for example first you convert all value in integer, make the summation and get the result back in double, so you not accumulate error... Error are amplifie whit operation like square root and power function...

    0 讨论(0)
  • 2021-02-04 13:43

    Most floating point output routines look to see if the answer is very close to being even when represented in base 10 and round the answer to actually be even on output. By setting the precision in this way you are short-circuiting this process.

    This rounding is done because almost no answer that comes out even in base 10 will be even (i.e. end in an infinite string of trailing 0s) in base 2, which is the base in which the number is represented internally. But, of course, the general goal of an output routine is to present the number in a fashion useful for a human being, and most human beings in the world today read numbers in base 10.

    0 讨论(0)
  • 2021-02-04 13:43

    You want to use the manipulator called "Fixed" to format your digits correctly so they do not round or show in a scientific notation after you use fixed you will also be able to use set the precision() function to set the value placement to the right of the . decimal point. the example would be as follows using your original code.

     #include <iostream>
     #include <iomanip>
        int main() {
              using namespace std;
              #include <iomanip>
    
    
        double dValue = 0.19213;
        cout << fixed << setprecision(2) << dValue << endl
    
    
           }
    

    outputs as:

    dValue = 0.19
    
    0 讨论(0)
提交回复
热议问题