Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a good solution for R#'s complaint about loss of precision?

There was some code in my project that compared two double values to see if their difference exceeded 0, such as:

if (totValue != 1.0)

Resharper complained about this, suggesting I should use "EPSILON" and added just such a constant to the code (when invited to do so). However, it does not create the constant itself or suggest what value it should be. Is this a good solution:

const double EPSILON = double.Epsilon; // see http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx
. . .
if (Math.Abs(totValue - 1.0) > EPSILON)
    compValue = Convert.ToString(totValue*Convert.ToDouble(compValue));

?

UPDATE

I changed it to this:

const double EPSILON = 0.001;

...thinking that's probably both large and small enough to work for typical double vals (not scientific stuff, just "I have 2.5 of these," etc.)

like image 635
B. Clay Shannon-B. Crow Raven Avatar asked Oct 01 '22 13:10

B. Clay Shannon-B. Crow Raven


2 Answers

No, it is not a sensible value for your epsilon. The code you have is no different than a straight equality check.

double.Epsilon is the smallest possible difference that there can be between any two doubles. There is no way for any two doubles to be closer to each other than by being double.Epsilon apart, so the only way for this check to be true is for them to be exactly equal.

As for what epsilon value you should actually use, that simply depends, which is why one isn't automatically generated for you. It all depends on what types of operations you're doing to the data (which affects the possible deviation from the "true value") along with how much precision actually care about in your application (and of course if the precision that you care about is greater than your margin of error, you have a problem). Your epsilon needs to be some precision value greater than (or equal to) the precision you need, while being less than the possible margin of error of all operations performed on either numeric value.

like image 68
Servy Avatar answered Oct 04 '22 19:10

Servy


Yes. But even better is to not use floating point. Use decimal instad.

However, if, for some reason, you have to stick to double never compare directly, that means, never rely on e.g. a-b == 0 with (a and b being some double values which are meant to be equal).

Floating point arithmetic is fast, but not precise, and taken that into account, R# is correct.

like image 37
alzaimar Avatar answered Oct 04 '22 20:10

alzaimar