def format_chf(value: int, with_currencysign: bool = True, plus_sign: bool = False) -> str: """ Formats a centime value into a commonly understood representation ("CHF -13.37"). :param value: The value to format, in centimes. :param with_currencysign: Whether to include the currency prefix ("CHF ") in the output. :param plus_sign: Whether to denote positive values with an explicit "+" sign before the value. :return: A human-readable string representation. """ sign: str = '' if value < 0: # As // and % round towards -Inf, convert into a positive value and prepend the negative sign sign = '-' value = -value elif plus_sign: sign = '+' # Split into full francs and fractions (centimes) full: int = value // 100 frac: int = value % 100 csign: str = 'CHF ' if with_currencysign else '' # Put it all together; centimes are always padded with 2 zeros return f'{csign}{sign}{full}.{frac:02}' def parse_chf(value: str) -> int: """ Parse a currency value into machine-readable format (integer centimes). The prefix "CHF", the decimal point, and digits after the decimal point are optional. :param value: The value to parse. :return: An integer representation of the value. :raises: Value error: If more than two digits after the decimal point are present. """ # Remove optional leading "CHF" and strip whitespace value = value.strip() if value.startswith('CHF'): value = value[3:] value = value.strip() if '.' not in value: # already is an integer; parse and turn into centimes return int(value, 10) * 100 # Split at the decimal point full, frac = value.split('.', 1) if len(frac) > 2: raise ValueError('Needs max. 2 digits after decimal point') elif len(frac) < 2: # Right-pad fraction with zeros ("x." -> "x.00", "x.x" -> "x.x0") frac = frac + '0' * (2 - len(frac)) # Parse both parts ifrac: int = int(frac, 10) ifull: int = int(full, 10) if ifrac < 0: raise ValueError('Fraction part must not be negative.') if full.startswith('-'): ifrac = -ifrac # Combine into centime integer return ifull * 100 + ifrac