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.开发者_如何学C75 ;
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
- you are not outputting the entire value, use
cout << setprecision(number_of_digits) << score1 << endl;
- 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 shows you that the difference is not lost, but actually as big as you'd expect (up to floating point accuracy, which is 15 decimal digits for double).
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
精彩评论