Problem with __sub__

Egon Frerich egon at frerich.eu
Thu Mar 23 13:44:13 EDT 2023


The class Betragswert is used for numerical values as string or integer 
and for additions and subtraction.

If on the left side is '0' the result of a subtraction is wrong.

*    b1 = Betragswert(500)
     b2 = 0 + b1
     b3 = 0 - b1
     b4 = 5 + b1
     b5 = 5 - b1*

print(b1, b2, b3, b4, b5) shows 5,00 5,00 5,00 5,05 4,95; the third 
value (b3) should be -5,00 (not 5,00).

Why is the substraction wrong?

This is the module:

import locale

locale.setlocale(locale.LC_ALL, "")
Trennzeichen = locale.localeconv()["thousands_sep"]

def bereinigen(t):
         lg = len(t)
         if lg > 0:
             if t[lg-1] == '\n':
                 return t[0:lg-1]
         return t


class Betragswert:
     def __init__(self, Wert):
         self._Betrag = 0
         if isinstance(Wert, type("123")):
             "Zeichenkette wurde übergeben"
             self._Betrag = _zeichenketteNACHganzzahl(Wert)
             return
         if isinstance(Wert, type(23)):
             "Cents wurden übergeben"
             self._Betrag = int(Wert)
             return
         if isinstance(Wert, type(self)):
             "Instanz der Klasse Betragswert wurde übergeben"
             self._Betrag = Wert.copy()
             return
         raise TypeError("Umsetzung als Betragswert nicht möglich: " + 
repr(Wert))

     def __str__(self):
         e, c = divmod(abs(self._Betrag), 100)
         cents = repr(c)
         cents = "0" * (2 - len(cents)) + cents
         return (
             "-"[: self._Betrag < 0]
             + locale.format_string("%d", e, grouping=1)
             + locale.localeconv()["decimal_point"]
             + cents
         )

     def __repr__(self):
         return "Betragswert " + repr((str(self)))

     def copy(self):
         return self._Betrag

     def __cmp__(self, anderer):
         return cmp(self._Betrag, Betragswert(anderer)._Betrag)

     def __neg__(self):
         return Betragswert(-self._Betrag)

     def __abs__(self):
         if self._Betrag >= 0:
             return self.copy()
         else:
             return -self._Betrag

     def __add__(self, zweiter):
         if not isinstance(zweiter, type(self)):
             zweiter = Betragswert(zweiter)
         return Betragswert(self._Betrag + zweiter._Betrag)

     def __radd__(self, zweiter):
         if not isinstance(zweiter, type(self)):
             zweiter = Betragswert(zweiter)
         return Betragswert(self._Betrag + zweiter._Betrag)


     def __sub__(self, zweiter):
         if not isinstance(zweiter, type(self)):
             zweiter = Betragswert(zweiter)
         return Betragswert(self._Betrag - zweiter._Betrag)

     def __rsub__(self, zweiter):
         if not isinstance(zweiter, type(self)):
             zweiter = Betragswert(zweiter)
         return Betragswert(self._Betrag - zweiter._Betrag)

     def hol(self): # notwendig für Tests
         return self._Betrag

Reg_Ausdruck = (
     r"""
     \s*
     (?P<vorzeichen>[-+])?
     (
         (?P<vor>\d+) ("""
     + "\\"
     + locale.localeconv()["decimal_point"]
     + r"""
                         (?P<nach>\d*))?
     |
         """
     + "\\"
     + locale.localeconv()["decimal_point"]
     + r"""
                          (?P<nurnach>\d+)
     )
     \s* $
"""
)
import re

_parser = re.compile(Reg_Ausdruck, re.VERBOSE).match

del re


def _zeichenketteNACHganzzahl(s):
     s = bereinigen(s)
     """s --> L"""
     s = s.replace(Trennzeichen, "")
     m = _parser(s)
     if m is None:
         raise ValueError("Dies ist keine Zahl: " + repr(s))

     vor = m.group("vor")
     if vor is None:
         vor = "0"
         nach = m.group("nurnach")
     else:
         nach = m.group("nach")
         if nach is None or nach == "":
             nach = "0"
     if len(nach) == 1:
         nach = nach + "0"
     elif len(nach) > 2:
         nach = nach[0:2]
     b1 = Betragswert(500)
     b2 = 0 + b1
     b3 = 0 - b1
     b4 = 5 + b1
     b5 = 5 - b1
     z = int(vor) * 100 + int(nach)

     if m.group("vorzeichen") == "-":
         z = -z
     return z


if __name__ == '__main__':
     b1 = Betragswert(500)
     b2 = 0 + b1
     b3 = 0 - b1
     b4 = 5 + b1
     b5 = 5 - b1
     print(b1, b2, b3, b4, b5)






More information about the Python-list mailing list