Absolutwert berechen (ohne abs())

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
PatrickF
User
Beiträge: 27
Registriert: Sonntag 1. Mai 2022, 09:43

Hallo zusammen,

ich beschäftige mich gerade mit dem Buch "Konkrete Mathematik" und den ersten Python-Schritten.

Eine Aufgabe hier lautet wie folgt:
Aufgabe 13: Schreiben Sie eine Python-Funktion, die zwei Argumente akzeptiert und von den beiden das zurückgibt, das weiter von null entfernt ist. Wenn die Argumente 3 und −7 sind, soll also z.B. −7 zurückgegeben werden.
Die Funktion abs() ist an dieser Stelle noch nicht eingeführt.

Meine Lösung:

Code: Alles auswählen

def abstand(n,m):
    n1=n #Hilfsvariablen, um den Ursprungswert zu speichern
    m1=m
    
    if n < 0:
         n=n*(-1) #Absolutbetrag berechnen
    if m < 0:
        m=m*(-1)

    if m==0 and n==0:
        print ("Beide Zahlen sind Null.")
    elif m1==n1:
        print ("Die Zahlen sind gleich.")
    elif m==n:
        print ("Der Abstand ist gleich.") #Betrag ist gleich
    elif m>n:
        print (m1,"ist weiter von Null entfernt.") 
    else:
        print (n1,"ist weiter von Null entfernt.")
Ist der Code halbwegs praktikabel, oder viel zu umständlich? Ich weiß z.B. dass man auch "n=-n" statt "n*(-1)"schreiben kann, aber ich wollte das möglichst 'mathematisch' ausdrücken. Habe versucht die Sonderfällt (0 etc.) gleich mit abzufangen.

Wie gesagt, abs() ist zu diesem Zeitpunkt noch nicht bekannt, vorausgesetzt werden nur Variablen und Schleifen bzw. if/elif/else. Geht halt um das Erlernen der Grundlagen.

Gruß
Patrick
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

`-n` ist genauso „mathematisch” wie `-1 * n`.
Irgendwelche Zahlen an Variablennamen anzuhängen macht die Namen nicht sehr aussagekräftig.
Den ursprünglichen Wert umzubennen und den Wert der übergebenen Variable zu verändern ist verwirrend. Warum nicht für den geänderten Wert einen neuen Namen vergeben? `absolute_n`?
`abstand` ist ein irreführender Name für eine Funktion die `informationen_über_den_abstand_ausgeben` macht.
Laut Aufgabenstellung soll die Funktion aber etwas zurückgeben.
nezzcarth
User
Beiträge: 1765
Registriert: Samstag 16. April 2011, 12:47

PatrickF hat geschrieben: Sonntag 1. Mai 2022, 09:57 Die Funktion abs() ist an dieser Stelle noch nicht eingeführt

Ist der Code halbwegs praktikabel, oder viel zu umständlich?
Den Betrag kann man ja durch Potenzen ausdrücken und Potenzierung ist ein Kernbestandteil von Python. Du kannst dir "abs" also leicht selbst definieren. Die eigentliche Funktion für den Abstand ist dann bei mir wenige Zeilen lang und enthält nur grundlegende Sprachmittel. Je nachdem muss man sich jedoch noch Gedanken darüber machen, welches Element zurückgegeben werden soll, wenn beide gleich weit von Null entfernt sind.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1244
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Code: Alles auswählen

def zero_distance(a, b):
    """
    Die Funktion liefert a zurück, wenn die Distanz zu 0 größer als bei b ist.
    
    Anmerkung:
    Wenn der Absolut-Wert von a und b gleich ist, wird a zurückgegeben.    
    """
    a_abs, b_abs = a, b
    if a < 0:
        a_abs *= -1
    if b < 0:
        b_abs *= -1
        
    # falls max auch noch nicht verwendet werden darf
    return a if a_abs >= b_abs else b
Bei der Funktion wird a bevorzugt. Ich denke, das hat der Autor vergessen zu erwähnen, was passieren soll, wenn beide Distanzen gleich sind.
Man könnte entweder eine der beiden Argumente bevorzugen oder man vergleicht die originalen Zahlen und nimmt dann die kleinere oder größere (je nachdem, was man will)
Ich habe das Buch auch, aber das liegt im Büro am Arbeitsplatz.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
dirk009
User
Beiträge: 27
Registriert: Donnerstag 3. Juni 2021, 21:49

Hallo @PatrickF,

bei der Aufgabenstellung ist nicht alles spezifiziert worden. Hier mein Entwurf:

Code: Alles auswählen

def abstand(x,y):
    return x if x*x > y*y else y

if __name__ == '__main__':
    print(abstand(3, -7))
    print(abstand(0, -7))
    print(abstand(3, -3))
    print(abstand(7, 7))
    
Benutzeravatar
__blackjack__
User
Beiträge: 14078
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Und nicht vergessen mit inf, -inf, und NaN zu testen, ob da auch sinnvolle Ergebnisse raus kommen. 🤓
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
PatrickF
User
Beiträge: 27
Registriert: Sonntag 1. Mai 2022, 09:43

Sirius3 hat geschrieben: Sonntag 1. Mai 2022, 10:45 `-n` ist genauso „mathematisch” wie `-1 * n`.
Irgendwelche Zahlen an Variablennamen anzuhängen macht die Namen nicht sehr aussagekräftig.
Den ursprünglichen Wert umzubennen und den Wert der übergebenen Variable zu verändern ist verwirrend. Warum nicht für den geänderten Wert einen neuen Namen vergeben? `absolute_n`?
`abstand` ist ein irreführender Name für eine Funktion die `informationen_über_den_abstand_ausgeben` macht.
Laut Aufgabenstellung soll die Funktion aber etwas zurückgeben.
Ja, die Funktion hätte ich wohl einfach "Betrag" nennen können. Mit den Namen muss sich noch einspielen. Hier gefiel mir "print" besser als "return", obwohl ich auch so eine Variante hatte.
PatrickF
User
Beiträge: 27
Registriert: Sonntag 1. Mai 2022, 09:43

nezzcarth hat geschrieben: Sonntag 1. Mai 2022, 11:55
PatrickF hat geschrieben: Sonntag 1. Mai 2022, 09:57 Die Funktion abs() ist an dieser Stelle noch nicht eingeführt

Ist der Code halbwegs praktikabel, oder viel zu umständlich?
Den Betrag kann man ja durch Potenzen ausdrücken und Potenzierung ist ein Kernbestandteil von Python. Du kannst dir "abs" also leicht selbst definieren. Die eigentliche Funktion für den Abstand ist dann bei mir wenige Zeilen lang und enthält nur grundlegende Sprachmittel. Je nachdem muss man sich jedoch noch Gedanken darüber machen, welches Element zurückgegeben werden soll, wenn beide gleich weit von Null entfernt sind.
Ja, hinterher ist man immer...

Dass man per Quadrat einen negativen Term positiv macht ist mir einfach nicht eingefallen.

Die Frage nach dem Rückgabewert bei Gleichheit und bei Null habe ich ja berücksichtigt.
PatrickF
User
Beiträge: 27
Registriert: Sonntag 1. Mai 2022, 09:43

DeaD_EyE hat geschrieben: Sonntag 1. Mai 2022, 12:12

Code: Alles auswählen

def zero_distance(a, b):
    """
    Die Funktion liefert a zurück, wenn die Distanz zu 0 größer als bei b ist.
    
    Anmerkung:
    Wenn der Absolut-Wert von a und b gleich ist, wird a zurückgegeben.    
    """
    a_abs, b_abs = a, b
    if a < 0:
        a_abs *= -1
    if b < 0:
        b_abs *= -1
        
    # falls max auch noch nicht verwendet werden darf
    return a if a_abs >= b_abs else b
Bei der Funktion wird a bevorzugt. Ich denke, das hat der Autor vergessen zu erwähnen, was passieren soll, wenn beide Distanzen gleich sind.
Man könnte entweder eine der beiden Argumente bevorzugen oder man vergleicht die originalen Zahlen und nimmt dann die kleinere oder größere (je nachdem, was man will)
Ich habe das Buch auch, aber das liegt im Büro am Arbeitsplatz.
Hat er tatsächlich nicht vergessen:
Aufgabe 14: Begründen Sie, warum die letzte Aufgabe nicht ausreichend präzise beschrieben hat, was die Funktion machen soll. Wie kann man die Aufgabe besser formulieren?
Die Sonderfälle habe ich ja versucht zu berücksichtigen, inklusive der Null.
PatrickF
User
Beiträge: 27
Registriert: Sonntag 1. Mai 2022, 09:43

__blackjack__ hat geschrieben: Sonntag 1. Mai 2022, 12:47 Und nicht vergessen mit inf, -inf, und NaN zu testen, ob da auch sinnvolle Ergebnisse raus kommen. 🤓
Dazu hab ich jetzt nichts Erhellendes beim googlen gefunden.

(Sorry dass ich so viel zitiere, habe keine Multiquote-Funktion gefunden).
PatrickF
User
Beiträge: 27
Registriert: Sonntag 1. Mai 2022, 09:43

dirk009 hat geschrieben: Sonntag 1. Mai 2022, 12:21 Hallo @PatrickF,

bei der Aufgabenstellung ist nicht alles spezifiziert worden. Hier mein Entwurf:

Code: Alles auswählen

def abstand(x,y):
    return x if x*x > y*y else y
...
Ja, mit dem Quadrieren hätte mir einfallen müssen, peinlich...schrieb ich ja schon oben...
Benutzeravatar
Dennis89
User
Beiträge: 1562
Registriert: Freitag 11. Dezember 2020, 15:13

"When I got the music, I got a place to go" [Rancid, 1993]
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Das mit NaN ist ein ernsthaftes Problem:

Code: Alles auswählen

In [1]: def abstand(x,y):^M
   ...:     return x if x*x > y*y else y
   ...:

In [2]: abstand(float('nan'), 1)
Out[2]: 1

In [3]: abstand(1, float('nan'))
Out[3]: nan
Hier haben wir ein inkonsistentes Verhalten, weil mal der Wert und mal der nicht-Wert als Ergebnis zurückgeliefert wird.
Die korrekte Lösung sieht dann auf den ersten Blick etwas ungewöhnlich aus:

Code: Alles auswählen

def abstand(x,y):
    if x != x or y != y:
        return float('nan')
    return x if x*x > y*y else y
oder um komplexe Zahlen korrekt zu behandeln:

Code: Alles auswählen

def abstand(x,y):
    if x != x or y != y:
        return float('nan')
    return x if (x * x.conjugate()).real > (y * y.conjugate()).real else y
Antworten