From 6d24c26b5240293e1a2890343d09412b358e7a22 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 20 Aug 2012 12:46:32 +0100 Subject: [PATCH] MDL-31837 numerical tolerance: better handling of very small tolerances. The changes between Moodle 1.9 and 2.1 made the marking of very small answers like 10^-20 almost impossible. This change fixes it. This fix is almost entirely due the the careful research of Pierre Pichet, who carefully testing various proposals, and worked out that this one seemed best. --- question/type/numerical/question.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/question/type/numerical/question.php b/question/type/numerical/question.php index 017af6bcf7e..49930af273e 100644 --- a/question/type/numerical/question.php +++ b/question/type/numerical/question.php @@ -323,10 +323,13 @@ class qtype_numerical_answer extends question_answer { throw new coding_exception('Cannot work out tolerance interval for answer *.'); } + // Smallest number that, when added to 1, is different from 1. + $epsilon = pow(10, -1 * ini_get('precision')); + // We need to add a tiny fraction depending on the set precision to make // the comparison work correctly, otherwise seemingly equal values can // yield false. See MDL-3225. - $tolerance = (float) $this->tolerance + pow(10, -1 * ini_get('precision')); + $tolerance = abs($this->tolerance) + $epsilon; switch ($this->tolerancetype) { case 1: case 'relative': @@ -334,8 +337,7 @@ class qtype_numerical_answer extends question_answer { return array($this->answer - $range, $this->answer + $range); case 2: case 'nominal': - $tolerance = $this->tolerance + pow(10, -1 * ini_get('precision')) * - max(1, abs($this->answer)); + $tolerance = $this->tolerance + $epsilon * max(abs($this->tolerance), abs($this->answer), $epsilon); return array($this->answer - $tolerance, $this->answer + $tolerance); case 3: case 'geometric':