Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I recently designed a time series module where my time series is essentially a SortedDictionnary<DateTime, double>.

Now I would like to create unit tests to make sure that this module is always working and producing the expected result.

A common operation is to compute the performance between the points in the time series.

So what I do is create a time series with, say, {1.0, 2.0, 4.0} (at some dates), and I expect the result to be {100%, 100%}.

The thing is, if I manually create a time series with the values {1.0, 1.0} and I check for equality (by comparing each point), the test would not pass, as there will always be inaccuracies when working with binary representations of real numbers.

Hence, I decided to create the following function:

private static bool isCloseEnough(double expected, double actual, double tolerance=0.002)
{
    return squaredDifference(expected, actual) < Math.Pow(tolerance,2);
}

Is there another common way of dealing with such a case?

share|improve this question

4 Answers 4

I can think of two other ways to deal with this problem:

You can use Is.InRange:

Assert.That(result, Is.InRange(expected-tolerance, expected+tolerance));

You can use Math.Round:

Assert.That(Math.Round(result, sigDigits), Is.EqualTo(expected));

I think that both ways are more expressive than a dedicated function, because the reader can see precisely what's going on with your number before it gets compared to the expected value.

share|improve this answer
2  
Just a note that this answer is NUnit specific and showcases the "Constraing-based" assertion model. The classic assertion model would look like: Assert.AreEqual(expected, actual, tolerance); –  RichardM Feb 7 '12 at 14:16
    
@RichardM: Post that as an answer and I will select it accept it. –  SRKX Feb 7 '12 at 14:22
    
The answer by @dasblinkenlight is correct, just adding some detail (since it may not be clear - the classic assertion model is also NUnit). Other test frameworks (not MSTest) likely have their own assert model to deal with floating point values. –  RichardM Feb 7 '12 at 14:26
1  
Assert.That(result, Is.InRange(expected-tolerance, expected+tolerance)); will fail if tolerance/abs(expected) < 1E-16. –  quant_dev Feb 7 '12 at 15:50
    
@quant_dev You are absolutely right. Since OP talks about calculating returns as percentages, I assumed that abs(expected) would be single to double digits. I also assumed the tolerance in the vicinity of 1E-9. Under these assumptions this admittedly simplistic approach could serve you reasonably well (I use Is.InRange in my tests). –  dasblinkenlight Feb 7 '12 at 16:05
up vote 4 down vote accepted

As RichardM suggested, if you do not use NUnit, the best way seems to be using Assert.AreEqual(double,double,double), where the last one is the precision.

share|improve this answer

It depends what you do with the numbers. If you are testing a method which is supposed to e.g. select an appropriate value from an input set based on some criteria, then you should test for strict equality. If you're doing floating-point calculations, usually you will need to test with a non-zero tolerance. How big the tolerance is depends on the calculations, but with double precision a good starting point is to choose 1E-14 relative tolerance for simple calculations and 1E-8 (tolerance) for more complicated ones. YMMV of course, and you need to add some small absolute tolerance if the expected result is 0.

share|improve this answer

I think this should do it.

Assert.That(result, Is.EqualTo(a).Within(double.Epsilon));
share|improve this answer
    
This is not included in the basic .Net test framework. –  SRKX Feb 7 '12 at 15:42
1  
Using absolute precision will fail if a is large. –  quant_dev Feb 7 '12 at 15:49
1  
@SRXK: Yeah, sorry, I didn't think about MSTest. However, using double.Epsilon as a tolerance should still be effective. –  pdr Feb 7 '12 at 15:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.