durchschnittsrechner.py

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
funny0017

Entwickeln Sie ein Programm zur Berechnung von Mittelwerten (Durchschnitt) für beliebig viele positive Zahlen (Kommazahlen, einschließlich Null). Erweitern Sie das Programm um eine Diagrammdarstellung der eingegebenen Werte (siehe Beispiel, Kommazahlen sollen gerundet werden). Verwenden Sie nur Variablen, Schleifen, Ein- und Ausgabefunktionen, Umwandlungsfunktionen für Text in Zahlen, round(…) und grundlegende Rechenoperationen für die Realisierung.

Beispielhafter Programmdurchlauf:

Bitte Wert eingeben (<0 beendet): 3.3
Bitte Wert eingeben (<0 beendet): 3.8
Bitte Wert eingeben (<0 beendet): 4.2
Bitte Wert eingeben (<0 beendet): 4.7
Bitte Wert eingeben (<0 beendet): -1

Diagramm:
###
####
####
#####

Durchschnitt: 4.0

Wie programmiere ich Umwandlungsfunktionen für Text in Zahlen, round(…)???
Wie kann ich Kommazahlen als Eingabe programmieren??

Code: Alles auswählen

print("Durchschnittsberechnung")
summe= 0
wert = int (input ("Bitte ersten Wert eingeben"))
summe = Wert
anzahl = 1
while not note==0
while note>=0
wert = int(input("Bitte weitere Werte eingben:"))
summe= summe+wert
anzahl= anzahl+1
durchschnitt = summe/anzahl
print(durchschnitt)
Zuletzt geändert von cofi am Dienstag 11. November 2014, 13:42, insgesamt 1-mal geändert.
Grund: Python Tags ergaenzt
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Ohne Zuweisungen wird das echt eine harte Aufgabe.

@funny0017: Umwandlungsfunktion für Text in Zahlen ist float.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Ohne Einrückungen ist der Quelltext nicht sinnvoll lesbar. Es sieht allerdings so aus, als ob der Code auch mit Einrückungen einige massive Probleme hat.

Wenn du zusätzlich das gezeigte Diagramm mit den "#" erstellen sollst, dann wäre es wohl am besten, wenn du alle eingegebenen Werte in einer Liste speicherst. Die dazu passende Ausgabe und Berechnung kannst du durchführen, sobald alle Werte gelesen wurden.

Eingaben mit Komma können durch float nicht erkannt und umgewandelt werden. Wenn du so etwas haben willst, dann musst du vor der Umwandlung erst das Komma durch einen Punkt ersetzen. Dazu bietet sich die replace-Methode eines Strings an.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@/me: das sind aber alles verbotene Funktionen: Listen, replace :cry: :cry: :cry:
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Sirius3 hat geschrieben:@/me: das sind aber alles verbotene Funktionen: Listen, replace :cry: :cry: :cry:
Das ist in der Tat sehr bedauerlich.

Hätte man die Werte in einer Liste könnte man sonst problemlos alles ausgeben.

Code: Alles auswählen

print('Diagramm\n{}\n\nDurchschnitt: {}'.format(
    '\n'.join('#' * int(round(value)) for value in values),
    sum(values) / len(values)) if len(values) > 0 else '')
garreth
User
Beiträge: 41
Registriert: Donnerstag 23. Oktober 2014, 12:04

Endlich mal wieder ein Thema zu dem ich auch etwas sagen kann.

1. Die zwei While Schleifen ergeben so keinen Sinn. Ersetze sie mit einer Endlosschleife, die wir nach der Eingabe einer Zahl kleiner Null mittels "break" beenden.
2. Die Variable "note", die als Abbruchbedinung deiner Schleifen dient kommt sonst im Programm nicht vor
3. Du wandelst die Variable "wert" absichtlich mittels "int()" in eine Ganzzahl um. Deine Nachkommastellen gehen so verloren. (Beispiel: int(3.9) = 3)
4. Du musst bei Variablen auf Groß- und Kleinschreibung achten. "Wert" und "wert" sind zwei verschiedene Variablen.
5. Nach dem "while" Befehl fehlt der Doppelpunkt und in den folgenden Zeilen die Einrückungen, die bei anderen Programmiersprachen mit der geschweiften Klammer zu vergleichen wäre.

Ich würde dir ganz dringend raten die Grundlagen von Python durchzuarbeiten. Du kannst zwar meine folgende Lösung kopieren, aber es würde dich nicht wirklich weiter bringen.

Code: Alles auswählen

diagramm = "Diagramm:\n"
summe = 0
anzahl = 0

while True:
    # Eingabe
    try:
        eingabe = float(input("Bitte Wert eingeben(<0 beendet): "))
    except:
        print("Bitte eine Zahl eingeben.")
        continue

    # Verarbeitung
    if eingabe >= 0:
        summe += eingabe
        anzahl += 1
        diagramm = diagramm + ("#" * round(eingabe)) + "\n"
    else:
        print()
        break

# Ausgabe
print(diagramm)
try:
    print("Durchschnitt:", summe / anzahl)
except:
    print("Sie muessen minderstens einen Wert eingeben.")
Ja ich weiß in diesem Beispiel haben die try/except Anweisungen nichts zu suchen. Ich programmier trotzdem gern mit Ihnen.

Ich sehe gerade das meine if-Anweisung wohl auch verboten ist. Dann ist die Lösung:
Fehlerhaftes Beispiel entfernt
Zuletzt geändert von garreth am Donnerstag 13. November 2014, 13:35, insgesamt 1-mal geändert.
BlackJack

@garreth: Das zweite ``try``/``except`` kann man einfach durch eine Abfrage ersetzen. Was viel schlimmer ist, ist das beide ``except``\s nicht angeben welche Ausnahme(n) sie behandeln und damit behandeln sie *alle* Ausnahmen, was zu schwer auffindbaren Fehlern führen kann wenn da mal eine Ausnahme mit der man nicht gerechnet hat behandelt wird und man die deshalb nie zu Gesicht bekommt, das Programm die aber in der Regel völlig inadequat ”behandelt”. Beispielsweise bei `NameError`, `KeyboardInterrupt`, oder `MemoryError` ist die Aufforderung eine Zahl einzugeben zu schreiben und dann weiterzumachen sehr wahrscheinlich nicht die sinnvolle Reaktion. Was dort eigentlich behandelt werden sollte ist der `ValueError` der von `float()` ausgelöst wird, und sonst nichts.

``continue`` finde ich persönlich eine unübersichtliche Anweisung weil die einen unbedingten Spung im Programmablauf macht, der sich nicht optisch in der Formatierung des Quelltextes widerspiegelt. Und man nimmt sich die Möglichkeit etwas ans Schleifenende zu schreiben was am Ende von *jedem* Schleifendurchlauf passieren soll. Ausserdem erschwert ``continue`` das herausziehen von Quelltextteilen aus einer Schleife in eine eigene Funktion, weil dort das ``continue`` sich dann natürlich nicht mehr auf die Schleife beziehen kann aus der es eigentlich stammt. ``try`` kennt auch einen optionalen ``else``-Zweig mit dem man diese Probleme alle nicht hätte.
garreth
User
Beiträge: 41
Registriert: Donnerstag 23. Oktober 2014, 12:04

Hey BlackJack,

stimmt natürlich, die "except:" Anweisung ist sehr unschön und ich sollte mir das gar nicht erst angewöhnen. Auch der Tip mit der if-Anweisung ist sehr sinnvoll.

Ein Frage hätte ich zu meinem zweiten Beispiel ohne "if" Anweisung. Warum bricht die Schleife nicht gleich nach der Eingabe "-1" ab sondern läuft bis zum Ende durch. Somit ist das Ergebnis nicht richtig, da er immer die negative Zahl auf die Summe rechnet und die Anzahl der Eingaben um eins erhöht. Wie könnte man dies verhindern(ohne if-Anweisung)?

Die einzige Lösung die mir einfällt ist die negative Zahl der Summe nach der Schleife wieder wegzurechnen...

Code: Alles auswählen

diagramm = "Diagramm:\n"
summe = 0
anzahl = 0
eingabe = 0


while eingabe >= 0:
        eingabe = float(input("Bitte Wert eingeben(<0 beendet): "))

        summe += eingabe
        anzahl += 1
        diagramm = diagramm + ("#" * round(eingabe)) + "\n"
        
summe -= eingabe
anzahl -= 1

print()
print(diagramm + "Durchschnitt:", summe / anzahl)
BlackJack

@garreth: Warum sollte die Schleife gleich nach der Eingabe abbrechen? Die Bedingung wird danach ja nicht gleich geprüft sondern erst wenn die Schleife erneut durchlaufen wird.
garreth
User
Beiträge: 41
Registriert: Donnerstag 23. Oktober 2014, 12:04

Gebe ich "-1" als Abbruchbedingung ein so führt er die Schleife bis zum Ende aus und rechnet das Ergebnis + -1 und zählt die Anzahl um einen Hoch. Das Ergebnis ist dadurch falsch und muss nach Abbruch der Schleife um den negativen Wert wieder erhöht werden. Die Anzahl der Eingaben muss wieder um eins gesenkt werden und ich habe ein "\n" zuviel im String. Deswegen auch die aus meiner Sicht unschöne Addition der Strings "diagramm" und "Durchschnitt:".

Ich denke allerdings, dass an dieser Vorgehensweise kein Weg vorbei führt.
BlackJack

@garreth: Doch, man könnte eine Endlosschleife schreiben und die Prüfung direkt nach der Eingabe machen und gegebenfalls die Schleife mit ``break`` abbrechen. Ich denke mal das ``if`` nicht erlaubt sein soll ist eine Ungenauigkeit in der Aufgabenstellung. Notfalls könnte man ein ``while`` als ``if`` missbrauchen.
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

Dass kein if verwendet werden darf, erachte ich auch als ungenau. Zumal in der Aufgabenstellung von Variablen die Rede ist. Das wäre sehr schwierig:

Code: Alles auswählen

>>> a = 0
>>> id(a)
505626088
>>> a = a + 2
>>> id(a)
505626120
Man könnte interpretieren, dass die Aufgabenstellung 1 : 1 aus einer Übung einer anderen Sprache (z. B. Java, C, C++) übernommen wurde. Im Grunde soll die Aufgabenstellung davon abhalten, "vorgefertigte" Funktionen zu verwenden (bis auf die angebotenen). Das Verwenden der Sprache sollte sicherlich nicht eingeschränkt werden. Kommazahlen (1,2) sollten sicherlich auch nicht interpretiert werden. Das Beispiel sieht auch einen Dezimalpunkt vor.

So will ich auch mal eine "unorthodoxen" Methode auffahren:

Code: Alles auswählen

#!/usr/bin/env python3

#-- Input and output ----------------------------------------------------------
def read_number():
    return float(input('Bitte Wert eingeben(<0 beendet): '))

def print_result(xs):
    print('Diagramm:')
    for x in xs:
        print('#' * int(round(x)))
    print('Durchschnitt: {}'.format(average(xs)))
    
#-- Control flow --------------------------------------------------------------
def do_until(func, trait):
    while True:
        result = func()
        if trait(result): return
        yield result

#-- Numerics ------------------------------------------------------------------
def average(xs):
    return sum(xs) / len(xs)

#-- main-idiom ----------------------------------------------------------------
def main():
    print_result([e for e in do_until(read_number, lambda x: x < 0)])
    
if __name__ == '__main__':
    main()
Grüße ... bwbg
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Wenn man es schön übersichtlich haben will, dann kann man es auch so aufbauen:

Code: Alles auswählen

def input_special_float(message=''):
    while True:
        value = input(message).replace(',', '.')
        try:
            value = float(value)
            break
        except:
            pass
    return value


def get_values(message=None):
    values = []
    while True:
        value = input_special_float(message)
        if value < 0:
            break
        else:
            values.append(value)
    return values


def print_diagram(values, header=None):
    if header:
        print(header)
    for value in values:
        print('#' * int(round(value)))


def get_average(values):
    return sum(values) / len(values) if len(values) > 0 else None


def main():
    values = get_values(message='Bitte Wert eingeben (<0 beendet): ')
    if len(values) > 0: 
        print_diagram(values, header='\nDiagramm')
        average = get_average(values)
        print('\nDurchschnitt: {}'.format(average))

if __name__ == '__main__':
    main()
BlackJack

Mal ein bisschen exotischer: Python mit Lisp-Syntax. :-)

Code: Alles auswählen

#!/usr/bin/env hy
(import [functools [partial]])


(defun ask-number [prompt]
    (let [[result nil]]
        (while (nil? result)
            (try
                (setv result (float (raw_input prompt)))
                (catch [ValueError] (print "Bitte eine Zahl eingeben."))))
        result))


(defun ask-numbers [prompt]
    (take-while pos? (repeatedly (partial ask-number prompt))))


(defun print-diagramm [values]
    (print
        (.format
            "Diagramm:\n{0}"
            (.join "\n" (genexpr (* "#" (int (+ v 0.5))) [v values])))))


(defmain [&rest args]
    (let [[values (list (ask-numbers "Bitte Wert eingeben(<0 beendet): "))]]
        (print)
        (print-diagramm values)
        (print)
        (print "Durchschnitt:" (/ (sum values) (len values)))))
Antworten