Browse files

Merge branch 'MDL-31837_23' of git://github.com/timhunt/moodle into M…

…OODLE_23_STABLE
  • Loading branch information...
2 parents 6ec3ae6 + ff43c30 commit 4eb3f12797b89229397cf4cd2eb68eb920178e0d @nebgor nebgor committed Aug 28, 2012
Showing with 42 additions and 8 deletions.
  1. +5 −3 question/type/numerical/question.php
  2. +37 −5 question/type/numerical/tests/answer_test.php
View
8 question/type/numerical/question.php
@@ -320,19 +320,21 @@ public function get_tolerance_interval() {
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':
$range = abs($this->answer) * $tolerance;
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':
View
42 question/type/numerical/tests/answer_test.php
@@ -25,8 +25,10 @@
*/
global $CFG;
+require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
require_once($CFG->dirroot . '/question/type/numerical/question.php');
+
class qtype_numerical_answer_test extends advanced_testcase {
public function test_within_tolerance_nominal() {
$answer = new qtype_numerical_answer(13, 7.0, 1.0, '', FORMAT_MOODLE, 1.0);
@@ -38,16 +40,46 @@ public function test_within_tolerance_nominal() {
$this->assertFalse($answer->within_tolerance(8.01));
}
+ public function test_within_tolerance_nominal_zero() {
+ // Either an answer or tolerance of 0 requires special care. We still
+ // don't want to end up comparing two floats for absolute equality.
+
+ // Zero tol, non-zero answer.
+ $answer = new qtype_numerical_answer(13, 1e-20, 1.0, '', FORMAT_MOODLE, 0.0);
+ $this->assertFalse($answer->within_tolerance(0.9999999e-20));
+ $this->assertTrue($answer->within_tolerance(1e-20));
+ $this->assertFalse($answer->within_tolerance(1.0000001e-20));
+
+ // Non-zero tol, zero answer.
+ $answer = new qtype_numerical_answer(13, 0.0, 1.0, '', FORMAT_MOODLE, 1e-24);
+ $this->assertFalse($answer->within_tolerance(-2e-24));
+ $this->assertTrue($answer->within_tolerance(-1e-24));
+ $this->assertTrue($answer->within_tolerance(0));
+ $this->assertTrue($answer->within_tolerance(1e-24));
+ $this->assertFalse($answer->within_tolerance(2e-24));
+
+ // Zero tol, zero answer.
+ $answer = new qtype_numerical_answer(13, 0.0, 1.0, '', FORMAT_MOODLE, 1e-24);
+ $this->assertFalse($answer->within_tolerance(-1e-20));
+ $this->assertTrue($answer->within_tolerance(-1e-35));
+ $this->assertTrue($answer->within_tolerance(0));
+ $this->assertTrue($answer->within_tolerance(1e-35));
+ $this->assertFalse($answer->within_tolerance(1e-20));
+
+ // Non-zero tol, non-zero answer.
+ $answer = new qtype_numerical_answer(13, 1e-20, 1.0, '', FORMAT_MOODLE, 1e-24);
+ $this->assertFalse($answer->within_tolerance(1.0002e-20));
+ $this->assertTrue($answer->within_tolerance(1.0001e-20));
+ $this->assertTrue($answer->within_tolerance(1e-20));
+ $this->assertTrue($answer->within_tolerance(1.0001e-20));
+ $this->assertFalse($answer->within_tolerance(1.0002e-20));
+ }
+
public function test_within_tolerance_blank() {
$answer = new qtype_numerical_answer(13, 1234, 1.0, '', FORMAT_MOODLE, '');
$this->assertTrue($answer->within_tolerance(1234));
$this->assertFalse($answer->within_tolerance(1234.000001));
$this->assertFalse($answer->within_tolerance(0));
-
- $answer = new qtype_numerical_answer(13, 0, 1.0, '', FORMAT_MOODLE, '');
- $this->assertTrue($answer->within_tolerance(0));
- $this->assertFalse($answer->within_tolerance(pow(10, -1 * ini_get('precision') + 1)));
- $this->assertTrue($answer->within_tolerance(pow(10, -1 * ini_get('precision'))));
}
public function test_within_tolerance_relative() {

0 comments on commit 4eb3f12

Please sign in to comment.