简体   繁体   中英

How to get around rounding issues in floating point arithmetic in C++?

Im running into some issues with floating point arithmetic not being accurate. I'm trying to calculate a score based on a weighted formula where every input variable weighs about as much as 20 times the next significant one. The inputs however are real numbers, so I ended up using a double to store the result. The code below has the problem of losing the difference between E1 and E2.

This code is performance sensitive, so I need to find an efficient answer to this problem. I thought of multiplying my inputs by a hundred and then using an int (since that would be precise enough I think), but I doubt that is the best solution, hence the question.

#include <iostream>

int main()
{
    double score1, score2;
    float a  = 2.75 ;
    float b  = 5.25 ;
    float c  = 5.25 ;
    float d  = 2.75 ;
    float E1 = 3    ;
    float E2 = 6    ;

    score1 = 20 * b - 1 * a + 0.05 * d  /* - 0.0025 * c*/ + 0.0001 * E1 ;
    score2 = 20 * b - 1 * a + 0.05 * d  /* - 0.0025 * c*/ + 0.0001 * E2 ;

    std::cout << score1 << std::endl;
    std::cout << score2 << std::endl;

    std::cin.get();
    return 0;
}

//ouputs:
//102.388
//102.388
  1. you are not outputting the entire value, use cout << setprecision(number_of_digits) << score1 << endl;
  2. how many valid digits do you need in your score computation?

I thought of multiplying my inputs by a hundred and then using an int (since that would be precise enough I think), but I doubt that is the best solution

Given the values you've shown, I would say it is.

http://ideone.com/qqTB3向您显示差异并未丢失,但实际上与您期望的一样大(达到浮点精度,即双精度为15位十进制数)。

Lets see what is happening in this code:

score1 = 20 * b - 1 * a + 0.05 * d  /* - 0.0025 * c*/ + 0.0001 * E1 ;

// Multiplication division happens first:

float  tmp1 = static_cast<float>(20) * b;      // 20 cast to float.
float  tmp2 = static_cast<float>(1)  * a;      // 1  cast to float.
double tmp3 = 0.05   * static_cast<double>(d); // d converted to double as 0.05 is double
double tmp4 = 0.0001 * static_cast<double>(E1);// E1 cast to double as 0.0001 is double

// Addition and subtraction now happen
float  tmp5  = tmp1 - tmp2;
double tmp6  = static_cast<double>(tmp5) + tmp3; // tmp5 cast to double as tmp3 is a double.
double tmp7  = tmp6 + tmp4;
score1       = tmp7;

If we do this in our heads:

tmp1 = 105.0
tmp2 =   2.75
tmp3 =   0.1375
tmp4 =   0.0003
tmp5 = 107.75
tmp6 = 107.8875
tmp7 = 107.8878

The precision should hold for those values:
But when you print out the default precision for doubles is 3 decimal places.

std::cout << 107.8878;
> 107.888

So set the precision:

std::cout << std::setprecision(15) << 107.8878 << "\n";
> 107.8878

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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