cardinal_pythonlib.rounding


Original code copyright (C) 2009-2022 Rudolf Cardinal (rudolf@pobox.com).

This file is part of cardinal_pythonlib.

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.


Rounding functions.

Note the general need to use Decimal, not float; otherwise rounding errors get silly, e.g. -150.1 + 0.05 == -150.04999999999998.

cardinal_pythonlib.rounding.num_dp_from_decimal(x: decimal.Decimal, with_negative_dp: bool = False) → int[source]

Return the number of decimal places used by a Decimal.

By default, this is what you’d expect; e.g. 123.45 has 2 dp, and 120 has 0 dp. But if you set with_negative_dp to True, then you if you pass in 200 you will get the answer -2.

Beware using str(); Decimals can look like 1E+2 rather than 100.

cardinal_pythonlib.rounding.range_roundable_up_to(y: Union[int, float, decimal.Decimal], dp: int = 0, with_description: bool = False) → Union[Tuple[decimal.Decimal, decimal.Decimal], Tuple[decimal.Decimal, decimal.Decimal, str]][source]

Suppose some value x was rounded to y with dp decimal places, using the “round half up” rounding method (see implementation in round_half_up()).

Given y and dp, this function finds the range [a, b), such that a <= b, within which x must have lain. The tuple returned is a, b.

If with_description is true, the tuple returned is a, b, range_description.

There are a large variety of rounding methods; see https://en.wikipedia.org/wiki/Rounding. Watch out – Python’s round() and Numpy’s np.around() don’t do that. See https://stackoverflow.com/questions/33019698/how-to-properly-round-up-half-float-numbers-in-python.

Note that dp can be negative, as in other Python functions.

cardinal_pythonlib.rounding.range_truncatable_to(y: Union[int, float, decimal.Decimal], dp: int = 0, with_description: bool = False) → Union[Tuple[decimal.Decimal, decimal.Decimal], Tuple[decimal.Decimal, decimal.Decimal, str]][source]

Some value x was truncated to y with dp decimal places, as per the implementation in truncate(). Return the range within which x must have lain.

The tuple returned is a, b, such that a <= b.

If with_description is true, the tuple returned is a, b, range_description.

If y is positive, the range returned is [a, b). If y is negative, the range returned is (a, b].

Note that dp can be negative, as in other Python functions.

cardinal_pythonlib.rounding.remove_exponent_from_decimal(d: decimal.Decimal) → decimal.Decimal[source]

Converts a decimal like 5.0E+3 to 5000. As per https://docs.python.org/3/library/decimal.html.

cardinal_pythonlib.rounding.round_half_up(x: Union[float, decimal.Decimal], dp: int = 0) → decimal.Decimal[source]

Rounds, with halves going up (positive).

(That is not the same as ROUND_HALF_UP in the decimal module!)

See also other methods, e.g.

cardinal_pythonlib.rounding.truncate(x: Union[float, decimal.Decimal], dp: int = 0) → decimal.Decimal[source]

Truncates a value to a certain number of decimal places.