Reputation:
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
Upvotes: 2
Views: 545
Reputation: 264331
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
Upvotes: 1
Reputation: 17131
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).
Upvotes: 1
Reputation: 36423
cout << setprecision(number_of_digits) << score1 << endl;
Upvotes: 4
Reputation: 61479
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.
Upvotes: 3