5.16.1 FixedPoint Rounding

The rounding algorithm used by FixedPoint when coercing floating point values to FixedPoint values can be set or re-defined by the developer to meet the requirements of the application. By default, FixedPoint objects use a type of rounding typically referred to as "Banker's Rounding" which is useful in financial applications. The available rounding algorithms include:
bankersRounding(dividend, divisor, quotient, remainder)
The default rounding algorithn, bankersRounding, rounds the last digit of precision up when a) the remainder is greater than 1/2 the divisor or b) the remainder is equal to 1/2 the divisor and the last digit to be kept is odd. This algorithm smoothly allocates possible rounding errors over the universe of possible results.

addHalfAndChop(dividend, divisor, quotient, remainder)
This rounding algorithm ALWAYS rounds "up" when the remainder is greater than or equal to 1/2 the divisor. In this case, round "up" means that the absolute value of the quotient will increase when rounded. This implementation of rounding is sometimes referred to as "add half and chop."

To change the rounding algorithm used by the FixedPoint class, set the value of the class method FixedPoint.round; e.g.,

 
>>>
>>> from fixedpoint import FixedPoint, addHalfAndChop
>>>
>>> # Demonstrate the default rounding
...  
>>> print FixedPoint("1.555")
1.56
>>> print FixedPoint("1.565")
1.56
>>> print FixedPoint("1.575")
1.58
>>> # Use a "round up" algorithm
... FixedPoint.round = addHalfAndChop
>>> 
>>> print FixedPoint("1.555")
1.56
>>> print FixedPoint("1.565")
1.57
>>> print FixedPoint("1.575")
1.58
>>> print FixedPoint("-1.555")
-1.56
>>> print FixedPoint("-1.565")
-1.57
>>> print FixedPoint("-1.575")
-1.58
>>>

Developers may customize the FixedPoint rounding algorithm by defining a newRoundingAlgorithm function as follows:

newRoundingAlgorithm(dividend, divisor, quotient, remainder)
The arguments to the rounding algorithm are all long values representing normalized values of the dividend, divisor, quotient and remainder. The function returns the rounded value for the quotient.

The normalizing process insures that the sign of the result is carried in the quotient, that the remainder is greater than or equal to 0 and that the divisor is greater than 0. This normalization process results in a reduction in "sign-bit headaches." The only real "decision" that the rounding algorithm variant needs to make is whether or not to add 1 to the quotient.

For example:

>>> from fixedpoint import FixedPoint
>>> def truncate(dividend, divisor, quotient, remainder):
...     """Don't round: truncate"""
...     return quotient
... 
>>> FixedPoint.round = truncate
>>> print FixedPoint("1.555")
1.55
>>> print FixedPoint("1.565")
1.56
>>> print FixedPoint("1.575")
1.57
>>>

Note that changing the rounding algorithm changes the algorithm for ALL new instances of FixedPoint objects including those created as the result of operations on FixedPoint objects. It is a good practice to set the rounding algorithm right after importing FixedPoint, and to avoid changing it in the body of the program.

See About this document... for information on suggesting changes.