• RE: Problem with __sub__

    From David Raymond@21:1/5 to All on Thu Mar 23 18:07:25 2023
    I believe your problem is __rsub__, not __sub__.
    When you have <something else> <operator> <something of this class> then that uses the "r" version of the operators.

    In your __rsub__ (used when you have <other> - <this>) you instead return <this> - <other> which is backwards.

    Notice how the final return should also be -4,95 and not the +4,95 it's returning.

    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?
    def __rsub__(self, zweiter):
    if not isinstance(zweiter, type(self)):
    zweiter = Betragswert(zweiter)
    return Betragswert(self._Betrag - zweiter._Betrag)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Egon Frerich@21:1/5 to All on Thu Mar 23 18:44:13 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)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)