Skip to content

Commit

Permalink
Add support for decimal places in Rounder
Browse files Browse the repository at this point in the history
  • Loading branch information
Splines committed Mar 15, 2024
1 parent 39ff7c4 commit a584206
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 31 deletions.
2 changes: 1 addition & 1 deletion src/api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

def config_init(
sigfigs: int = 2,
decimal_places: int = 2,
decimal_places: int = -1, # -1: "per default use sigfigs instead"
print_always: bool = False,
min_exponent_for_non_scientific_notation: int = -2,
max_exponent_for_non_scientific_notation: int = 3,
Expand Down
2 changes: 1 addition & 1 deletion src/api/res.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def res(
result = _Result(
name_res, value_res, unit_res, uncertainties_res, sigfigs_res, decimal_places_res
)
_Rounder.round_result(result, configuration.sigfigs)
_Rounder.round_result(result, configuration.sigfigs, configuration.decimal_places)
_res_cache.add(name, result)

return PrintableResult(result)
Expand Down
58 changes: 38 additions & 20 deletions src/application/rounder.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import List, Union

from domain.result import _Result
from domain.uncertainty import _Uncertainty
Expand All @@ -8,37 +8,50 @@
class _Rounder:

@classmethod
def round_result(cls, result: _Result, sigfigs_default: int) -> None:
def round_result(cls, result: _Result, sigfigs_default: int, decimal_places: int) -> None:
"""
In-place rounds all numerical fields of a result to the correct
number of significant figures.
Rounding hierarchy for uncertainties:
# Rounding hierarchy:
1. Is uncertainty exact? Do not round!
2. Round uncertainty according to the hierarchy below!
1. Is uncertainty exact? Do not round.
2. Round uncertainty according to the hierarchy below.
Rounding hierarchy:
1. Is value exact? Do not round! Round uncertainty according to value!
2. Is number of sigfigs given? Round value according to number of sigfigs! Round
uncertainties according to value.
3. Is number of decimal places given? Round value according to number of decimal places!
Round uncertainties according to value.
4. Is at least one uncertainty given? Round each uncertainty according to standard rules!
Round value according to uncertainty with lowest min exponent!
5. Round value to 2 sigfigs.
# Rounding hierarchy for inexact uncertainty:
1. Is result value exact?
Round uncertainty according to result value.
2. Is default for decimal places given (not -1) (see method param)?
Round value according to number of decimal places.
Round uncertainties according to value.
3. Is number of sigfigs of result given?
Round value according to number of sigfigs.
Round uncertainties according to value.
4. Is number of decimal places of result given?
Round value according to number of decimal places.
Round uncertainties according to value.
5. Is at least one uncertainty given?
Round each uncertainty according to standard rules.
Round value according to uncertainty with lowest min exponent.
6. Round value to the default for the sigfigs (see method param).
TODO: Warning message if user specifies exact value and sigfigs etc.
"""
cls._round_result(result, sigfigs_default)
cls._round_result(result, sigfigs_default, decimal_places)

short = result.get_short_result()
if short:
cls._round_result(short, sigfigs_default)
cls._round_result(short, sigfigs_default, decimal_places)

@classmethod
def _round_result(cls, result: _Result, sigfigs_default: int) -> None:
def _round_result(cls, result: _Result, sigfigs_default: int, decimal_places: int) -> None:
"""See the docstring of the public `round_result` for details."""

value = result.value
Expand All @@ -49,16 +62,22 @@ def _round_result(cls, result: _Result, sigfigs_default: int) -> None:
cls._uncertainties_set_min_exponents(uncertainties, value.get_min_exponent())

# Rounding hierarchy 2:
elif decimal_places != -1:
min_exponent = -decimal_places
value.set_min_exponent(min_exponent)
cls._uncertainties_set_min_exponents(uncertainties, min_exponent)

# Rounding hierarchy 3:
elif result.sigfigs is not None:
value.set_sigfigs(result.sigfigs)
cls._uncertainties_set_min_exponents(uncertainties, value.get_min_exponent())

# Rounding hierarchy 3:
# Rounding hierarchy 4:
elif result.decimal_places is not None:
value.set_min_exponent(-result.decimal_places)
cls._uncertainties_set_min_exponents(uncertainties, value.get_min_exponent())

# Rounding hierarchy 4:
# Rounding hierarchy 5:
elif len(uncertainties) > 0:
for u in uncertainties:
if u.uncertainty.is_exact():
Expand Down Expand Up @@ -88,4 +107,3 @@ def _uncertainties_set_min_exponents(
for u in uncertainties:
if not u.uncertainty.is_exact():
u.uncertainty.set_min_exponent(min_exponent)
return
14 changes: 5 additions & 9 deletions tests/playground.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
print()


wiz.config_init(decimal_places=3, print_always=True)

wiz.config_init(print_always=True, sigfigs=10)
wiz.config(sigfigs=2)
# wiz.config(decimal_places=2)

#############################
# EXAMPLES
Expand All @@ -27,7 +28,6 @@
wiz.res("a1", 1.0, r"\mm").print()
# a: 1.0 \mm

wiz.config(sigfigs=2)

wiz.res("1 b", 1.0, 0.01, r"\per\mm\cubed").print()
# b: (1.0 ± 0.01) \mm
Expand All @@ -40,18 +40,14 @@
).print()
# d: (1.0 ± 0.01 systematic ± 0.02 stat) \mm

# wiz.standard_sigfigs(4)

wiz.res("e", "1.0", r"\mm").print()
# e: 1.0 \mm

wiz.config(decimal_places=4)

# wiz.standard_sigfigs(3)

wiz.res("f", "1.0e1", 25e-1).print()
# f: 1.0

wiz.res("a", 42.0).print()

# wiz.res("g", 1.0, sys=0.01, stat=0.02, unit=r"\mm").print()
# g: (1.0 ± 0.01 sys ± 0.02 stat) \mm
# TODO: Why does this not work?
Expand Down

0 comments on commit a584206

Please sign in to comment.