mirror of
https://github.com/moodle/moodle.git
synced 2025-04-03 15:32:43 +02:00
MDL-60431 qtype_calculated: handle NAN and INF calculation outcomes
With significant-digits presentation mode, NAN would be formatted as 'NAN' followed by zeroes, which looks silly, and +INF would cause an execution timeout as Moodle tries to divide +∞ by 10 until it becomes less than 1, which can happen in a divide-by-zero situation. Note that the user can't answer NAN or INF to any question, but at this at least now looks consistent and also doesn't break Moodle in the case of +INF.
This commit is contained in:
parent
efb3d4e7a7
commit
be65ee093d
@ -335,7 +335,11 @@ class qtype_calculated_variable_substituter {
|
||||
* @return string formtted number.
|
||||
*/
|
||||
public function format_float($x, $length = null, $format = null) {
|
||||
if (!is_null($length) && !is_null($format)) {
|
||||
if (is_nan($x)) {
|
||||
$x = 'NAN';
|
||||
} else if (is_infinite($x)) {
|
||||
$x = ($x < 0) ? '-INF' : 'INF';
|
||||
} else if (!is_null($length) && !is_null($format)) {
|
||||
if ($format == '1' ) { // Answer is to have $length decimals.
|
||||
// Decimal places.
|
||||
$x = sprintf('%.' . $length . 'F', $x);
|
||||
|
@ -1857,6 +1857,9 @@ function qtype_calculated_calculate_answer($formula, $individualdata,
|
||||
// Something went wrong, so just return NaN.
|
||||
$calculated->answer = NAN;
|
||||
return $calculated;
|
||||
} else if (is_nan($answer) || is_infinite($answer)) {
|
||||
$calculated->answer = $answer;
|
||||
return $calculated;
|
||||
}
|
||||
if ('1' == $answerformat) { // Answer is to have $answerlength decimals.
|
||||
// Decimal places.
|
||||
|
@ -238,4 +238,19 @@ class qtype_calculated_test extends advanced_testcase {
|
||||
</pre>
|
||||
'));
|
||||
}
|
||||
|
||||
public function test_calculate_answer_nan_inf() {
|
||||
$answer = qtype_calculated_calculate_answer('acos(1.1)', [], 0.1, 1, 2, 2);
|
||||
$this->assertIsObject($answer);
|
||||
$this->assertNan($answer->answer);
|
||||
|
||||
$answer = qtype_calculated_calculate_answer('log(0.0)', [], 0.1, 1, 2, 2);
|
||||
$this->assertIsObject($answer);
|
||||
$this->assertInfinite($answer->answer); // Actually -INF.
|
||||
|
||||
// Dividing by zero is hard to test, so get +INF another way.
|
||||
$answer = qtype_calculated_calculate_answer('abs(log(0.0))', [], 0.1, 1, 2, 2);
|
||||
$this->assertIsObject($answer);
|
||||
$this->assertInfinite($answer->answer);
|
||||
}
|
||||
}
|
||||
|
@ -134,4 +134,12 @@ class qtype_calculated_variable_substituter_test extends advanced_testcase {
|
||||
$this->assertSame('0,12', $vs->format_float(0.12345, 2, 2));
|
||||
$this->assertSame('0,0012', $vs->format_float(0.0012345, 4, 1));
|
||||
}
|
||||
|
||||
public function test_format_float_nan_inf() {
|
||||
$vs = new qtype_calculated_variable_substituter([ ], '.');
|
||||
|
||||
$this->assertSame('NAN', $vs->format_float(NAN));
|
||||
$this->assertSame('INF', $vs->format_float(INF));
|
||||
$this->assertSame('-INF', $vs->format_float(-INF));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user