Add an implementation of python2 style round.
Python 3 has no way to access this implementation of rounding in the standard library. We implement it here so that we can continue to use it for grades calculation to keep regrading consistent. Currently we can't be confident that if we change the rounding behaviour we won't impact students. We can't be sure that students that were previously passing wouldn't suddenly no longer be passing. Given this, it's lower risk to just implement the old rounding strategy here and use it when we are rounding to calculate grades.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Helpers functions for grades and scores.
|
||||
"""
|
||||
import math
|
||||
|
||||
|
||||
def compare_scores(earned1, possible1, earned2, possible2, treat_undefined_as_zero=False):
|
||||
@@ -42,3 +43,26 @@ def is_score_higher_or_equal(earned1, possible1, earned2, possible2, treat_undef
|
||||
"""
|
||||
is_higher_or_equal, _, _ = compare_scores(earned1, possible1, earned2, possible2, treat_undefined_as_zero)
|
||||
return is_higher_or_equal
|
||||
|
||||
|
||||
def round_away_from_zero(number, digits=0):
|
||||
"""
|
||||
Round numbers using the 'away from zero' strategy as opposed to the
|
||||
'Banker's rounding strategy.' The strategy refers to how we round when
|
||||
a number is half way between two numbers. eg. 0.5, 1.5, etc. In python 2
|
||||
positive numbers in this category would be rounded up and negative numbers
|
||||
would be rounded down. ie. away from zero. In python 3 numbers round
|
||||
towards even. So 0.5 would round to 0 but 1.5 would round to 2.
|
||||
|
||||
See here for more on floating point rounding strategies:
|
||||
https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules
|
||||
|
||||
We want to continue to round away from zero so that student grades remain
|
||||
consistent and don't suddenly change.
|
||||
"""
|
||||
p = 10.0 ** digits
|
||||
|
||||
if number >= 0:
|
||||
return float(math.floor((number * p) + 0.5)) / p
|
||||
else:
|
||||
return float(math.ceil((number * p) - 0.5)) / p
|
||||
|
||||
@@ -7,7 +7,7 @@ from unittest import TestCase
|
||||
|
||||
import ddt
|
||||
|
||||
from ..grade_utils import compare_scores
|
||||
from ..grade_utils import compare_scores, round_away_from_zero
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -45,3 +45,15 @@ class TestGradeUtils(TestCase):
|
||||
assert is_higher is True
|
||||
assert 0 == percentage_1
|
||||
assert 0 == percentage_2
|
||||
|
||||
@ddt.data(
|
||||
(0.5, 1),
|
||||
(1.45, 1.5, 1),
|
||||
(-0.5, -1.0),
|
||||
(-0.1, -0.0),
|
||||
(0.1, 0.0),
|
||||
(0.0, 0.0)
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_round_away_from_zero(self, precise, expected_rounded_number, rounding_precision=0):
|
||||
assert round_away_from_zero(precise, rounding_precision) == expected_rounded_number
|
||||
|
||||
Reference in New Issue
Block a user