## WeBWorK Main Forum

### num_cmp behavior with 'tol' set

by Gavin LaRose -
Number of replies: 4
Hi all,

I have a problem with the answer evaluator
num_cmp( $ans, "tol"=>".0001") The correct answer is$ans = 1.9604; a student answers "1.9605" and it is marked wrong. However, "1.9603" is marked correct. My understanding of the "tol" parameter is that it is an absolute tolerance: the answer must be within "tol" of the correct answer to be marked correct. Here, however, |1.9604 - 1.9605| = |1.9604 - 1.9603| = .0001, so shouldn't both of these be marked correct (or both marked wrong)?

Thanks,
Gavin

### Re: num_cmp behavior with 'tol' set

by Davide Cervone -
Can you post the actual problem code (or point to the problem in the library)? I suspect the correct answer isn't EXACTLY 1.9604, and so 1.9603 is slightly closer than 1.9605 and fall within the tolerance while 1.9605 doesn't. You should not expect answers at the very edge of the tolerance to be well behaved. (Even things like the round-off error in converting 1.9603 and 1.9605 to binary can have an effect.)

Davide

### Re: num_cmp behavior with 'tol' set

by Gavin LaRose -
Hi Davide,

Your surmise is what I was thinking was happening, but couldn't see how that would be the case given how the answer is being generated.

The correct answer is generated approximately as follows
$ans = [assorted numerical calculations];$ans = round(10000*\$ans)/10000;
It's actually part of a Runge-Kutta problems for an ODE course, so the [assorted numerical calculations] are the calculations to generate the successive RK approximation. If it's useful I can include those, but I don't think they matter for this discussion.

Thanks,
Gavin

### Re: num_cmp behavior with 'tol' set

by Davide Cervone -
The problem is as I suspected. None of the numbers 1.9603, 1.9604, or 1.9605 can be represented accurately using 54 binary digits (the number used in a perl floating-point real) and so they each include conversion error due to conversion to binary. It turns out to be slightly different in each case, and for 1.9605 there is a round up in the conversion, while in the other two there is a round down. That means the difference between 1.9605 and 1.9604 is slightly larger than the difference between 1.9603 and 1.9604 (in terms of their floating-point binary representations). Because of the round-up in 1.9605, the difference is slightly larger than .0001.

You can see this by executing the following:

    perl -e 'print 1.9605-1.9604 , " <=> " , 1.9604-1.9603, "\n"'

which produces the output
    0.000100000000000211 <=> 9.99999999997669e-05

Note that the first difference is slightly greater than .0001 while the second is slightly less than .0001.

There is really nothing you can do about this; it's just the way real floating-point reals work. You can't count on values at the edge of the allowed precision to work accurately, as nearly all decimal numbers have conversion errors. (Since 10 is not a power of 2, the conversion between the two bases rarely produce finite representations in both, and so there will be loss when one representation is truncated or rounded).

Davide