diff --git a/mlair/helpers/helpers.py b/mlair/helpers/helpers.py index 8104c7c50517e05be14b05aaa9cea8d0e5ba32f4..b583cf7dc473db96181f88b0ab26e60ee225240d 100644 --- a/mlair/helpers/helpers.py +++ b/mlair/helpers/helpers.py @@ -122,6 +122,21 @@ def float_round(number: float, decimals: int = 0, round_type: Callable = math.ce return round_type(number * multiplier) / multiplier +def relative_round(x: float, sig: int) -> float: + """ + Round small numbers according to given "significance". + + Example: relative_round(0.03112, 2) -> 0.031, relative_round(0.03112, 1) -> 0.03 + + :params x: number to round + :params sig: "significance" to determine number of decimals + + :return: rounded number + """ + assert sig >= 1 + return round(x, sig-int(np.floor(np.log10(abs(x))))-1) + + def remove_items(obj: Union[List, Dict, Tuple], items: Any): """ Remove item(s) from either list, tuple or dictionary. diff --git a/test/test_helpers/test_helpers.py b/test/test_helpers/test_helpers.py index b850b361b09a8d180c5c70c2257d2d7be27c6cc0..70640be9d56d71e4f68145b3bb68fb835e1e27a5 100644 --- a/test/test_helpers/test_helpers.py +++ b/test/test_helpers/test_helpers.py @@ -15,7 +15,7 @@ import string from mlair.helpers import to_list, dict_to_xarray, float_round, remove_items, extract_value, select_from_dict, sort_like from mlair.helpers import PyTestRegex from mlair.helpers import Logger, TimeTracking -from mlair.helpers.helpers import is_xarray, convert2xrda +from mlair.helpers.helpers import is_xarray, convert2xrda, relative_round class TestToList: @@ -171,6 +171,39 @@ class TestFloatRound: assert float_round(-34.9221, 0) == -34. +class TestRelativeRound: + + def test_relative_round_big_numbers(self): + assert relative_round(101, 1) == 100 + assert relative_round(99, 1) == 100 + assert relative_round(105, 2) == 100 + assert relative_round(106, 2) == 110 + assert relative_round(106, 3) == 106 + + def test_relative_round_float_numbers(self): + assert relative_round(101.2033, 4) == 101.2 + assert relative_round(101.2033, 5) == 101.2 + assert relative_round(101.2033, 6) == 101.203 + + def test_relative_round_small_numbers(self): + assert relative_round(0.03112, 2) == 0.031 + assert relative_round(0.03112, 1) == 0.03 + assert relative_round(0.031126, 4) == 0.03113 + + def test_relative_round_negative_numbers(self): + assert relative_round(-101.2033, 5) == -101.2 + assert relative_round(-106, 2) == -110 + assert relative_round(-0.03112, 2) == -0.031 + assert relative_round(-0.03112, 1) == -0.03 + assert relative_round(-0.031126, 4) == -0.03113 + + def test_relative_round_wrong_significance(self): + with pytest.raises(AssertionError): + relative_round(300, -1) + with pytest.raises(TypeError): + relative_round(300, 1.1) + + class TestSelectFromDict: @pytest.fixture