Papier falten

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
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Hallo.
Ja, es geht um eine Uni-Aufgabe. Diese habe ich gelöst - zumindest so, dass sie funktioniert.
Die Aufgabe war es die Anzahl der Faltungen eines Papiers bis zum Mont auszurechnen.

Allerdings bin ich mit meiner Lösung noch etwas unzufrieden, da die erste Faltung ich sozusagen "manuell" mache und dann erst die Schleife ab Faltung 2 laufen lassen kann.
Seht ihr eine Möglichkeit, wie ich auch die erste Faltung in die Schleife bei der Deklaration von distanz_papier einarbeiten kann?

Code: Alles auswählen

papier_dicke = 0.1 # mm
ENTFERNUNG_ERDE_MOND = 384400 # km

def umrechnung_km_in_mm(km):
    km *= 1000 * 100 * 10
    return km

while True:
    faltungen = 1
    distanz_papier = papier_dicke * 2
    while distanz_papier < umrechnung_km_in_mm(ENTFERNUNG_ERDE_MOND):
        distanz_papier *= 2
        faltungen += 1
    break

print(faltungen)
Danke.
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Feedback1000: Was soll denn die ``while True:``-Schleife die genau *einmal* durchlaufen und dann bedingungslos mit ``break`` abgebrochen wird? Das macht keinen Sinn, denn dann ist das keine Schleife.

Und natürlich kann man sich den Schritt vor der Schleife sparen. Wenn man 0 Faltungen hat, welcher Distanz entspricht das ungefaltete Papier denn dann?

Übrigens würde man hier eventuell auch wieder aufpassen müssen ob sich Gleitkommazahlen und deren (Un)Genauigkeit auf das Ergebnis auswirken, denn 0.1 kann ja nicht intern nicht exakt abgebildet werden.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

@blackjack: in der Tat, die "while True:"-Schleife ist noch ein Überbleibsel aus der Testphase und wirklich sinnfrei. Zum Rundungsproblem:

Code: Alles auswählen

# V2

papier_dicke = 0.1 # mm
ENTFERNUNG_ERDE_MOND = 384400 # km

def umrechnung_km_in_mm(km):
    km *= 1000 * 100 * 10
    return km

faltungen = 0
distanz_papier = 0

while distanz_papier < umrechnung_km_in_mm(ENTFERNUNG_ERDE_MOND):
    if faltungen == 0:
        distanz_papier = round(papier_dicke * 2, 2)
    else:
        distanz_papier = round(distanz_papier * 2, 2)
    faltungen += 1
    print(f'Nach der Faltung {faltungen} hat das Papier eine Dicke von {distanz_papier}')

print(faltungen)
Was halst du davon?
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Feedback1000: Da ist jetzt ein eigentlich überflüssige ``if``-Abfrage, weil `distanz_papier` fälschlicherweise mit 0 initialisiert wird. Wenn das Papier gar nicht gefaltet ist, überbrückt das doch trotzdem eine Distanz. Das ungefaltete Blatt hat ja eine Dicke.

`round()` ändert nicht wirklich etwas an dem Problem, dass die Werte nicht verlustfrei intern dargestellt werden können. Ich weiss auch nicht ob das hier tatsächlich zu einem Problem führt, man muss halt drüber nachdenken/es überprüfen. Oder halt gleich nur mit ganzen Zahlen rechnen.

Ist Schleife eigentlich als Lösungsweg vorgegeben worden?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn man Kilometer mit einer Million multipliziert, dann sind das keine Kilometer mehr, warum speicherst Du das Ergebnis dann in einer Variable, die km heißt?
Warum ist die Entfernung Erde-Mond eine Konstante, die Papierdicke aber nicht?

Code: Alles auswählen

import math

PAPIERDICKE_IN_MM = 0.1
ENTFERNUNG_ERDE_MOND_IN_KM = 384400

faltungen = math.ceil(math.log2(ENTFERNUNG_ERDE_MOND_IN_KM / PAPIERDICKE_IN_MM * 1e6))
Benutzeravatar
DeaD_EyE
User
Beiträge: 1017
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Für SI-Präfixe kann man unterschiedliche Bibliotheken nutzen. Zuletzt ist z.B. prefixed erschienen: https://pypi.org/project/prefixed/
Pint gibt es schon länger und ist eher für numpy geeignet: https://pint.readthedocs.io/en/stable/

Code: Alles auswählen

import math
from prefixed import Float


PAPIERDICKE = Float("0.1m")
ENTFERNUNG_ERDE_MOND = Float("384400k")

faltungen = math.ceil(math.log2(ENTFERNUNG_ERDE_MOND / PAPIERDICKE))
Das selbe nochmal mit Pint.

Code: Alles auswählen

import math
from pint import UnitRegistry

ureg = UnitRegistry()


PAPIERDICKE = 0.1 * ureg.mm
ENTFERNUNG_ERDE_MOND = 384400 * ureg.km

faltungen = math.ceil(math.log2(ENTFERNUNG_ERDE_MOND / PAPIERDICKE))
42 hört sich gar nicht so viel an, ist aber ganz schön dick :-D
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Spasseshalber, und weil morgen der diesjährige Advent of Code anfängt, mal eine Lösung mit beiden Varianten (Formel und Schleife) in BASIC (auf einem VIC-20, sollte aber auch mit anderen Microsoft-BASICs und den meisten anderen Implementierungen funktionieren):

Code: Alles auswählen

10 REM 1KM IN MM
20 KM=1E6
30 REM ENTFERNUNG ZUM
40 REM MOND
50 EM=384400*KM
60 REM PAPIERDICKE IN
70 REM MILLIMETER
80 PD=0.1
90 REM
100 REM FALTUNGEN PER
110 REM FORMEL BE-
120 REM RECHNET:
130 F1=INT(LOG(EM/PD)/LOG(2)+.5)
140 PRINT F1;"FALTUNGEN"
150 REM
160 REM FALTUNGEN PER
170 REM SCHLEIFE ER-
180 REM MITTELT:
190 F2=0:D=PD
200 IF D>=EM THEN 230
210 F2=F2+1:D=D*2
220 GOTO 200
230 PRINT F2;"FALTUNGEN"
240 IF F1<>F2 THEN PRINT"FEHLER!"
Das jetzt hier auf einem *Riesen*monitor und mit Syntaxhighlighting zu sehen, statt den 22 mal 23 Zeichen auf dem VIC-20, ist ja sowas von luxuriös… 😎
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Hier mal der Stand der Dinge, in der ich alle (so hoffe ich) eurer Hinweise eingearbeitet habe:

Code: Alles auswählen

# V3

PAPIERDICKE_IN_MM = 0.1
ENTFERNUNG_ERDE_MOND_IN_KM = 384400
faltungen = 0
distanz_papier = PAPIERDICKE_IN_MM

def umrechnung_km_in_mm(mm):
    mm *= 1000 * 100 * 10
    return mm

while distanz_papier < umrechnung_km_in_mm(ENTFERNUNG_ERDE_MOND_IN_KM):
    # print(f'Vor der Faltung {faltungen+1} ist das Papier {distanz_papier}mm breit')
    if faltungen != 0:
        distanz_papier = round(distanz_papier * 2, 2)
    else:
        distanz_papier = round(PAPIERDICKE_IN_MM * 2, 2)
    faltungen += 1
    # print(f'Nach der Faltung {faltungen} ist das Papier {distanz_papier}mm breit')
    # print('---------------------------------------------------------------------------')

print(faltungen)
@__blackjack__:
  • falsche Initialisierung habe ich behoben. In diesem zuge habe ich auch die Verzweigung etwas umgebaut - in dem Glauben, dass ich damit die Performance verbessert habe (zwar spielt das bei dieser geringen Durchlaufzahl keine Rolle, aber in meiner naiven Welt habe ich damit etwas gewonnen)
  • Das Rundungsproblem ist zwar vorhanden, aber erst in einer nicht signifikanten Nachkommastelle, sodass ich dieses Problem momentan ignoriere
  • Bezüglich Schleife Ja/Nein: ja, es ist explizit gefordert, "mehr können wir auch nicht" bzw. sollen noch nichts darüber hinaus verwenden.
    Ich vermute, dass du auf eine fertige Methode aus einer externen Bibliothek anspielst (so, wie es auch Sirius3 und DeaD_EyE vorgeschlagen haben)?
    Der Vollständigkeithalber hier mal die Aufgabenstellung:
    ## Aufagbe

    Ein Stück Papier, mit der Dicke von 0,1mm, wird immer wieder in der Hälfte gefalten. Wie viele Faltungen benötigt es um den Mond zu erreichen. Die Entfernung zum Mond beträgt 384400km.
    Schreiben Sie ein Python-Programm, und geben Sie an wie viele Faltungen benötigt sind.

    Beachten Sie dabei folgende Vorgaben:
    - **Nutzen Sie eine Schleife** um die Problemstellung zu lösen
    - Definieren Sie eine Variable namens **`faltungen`**, in der am Ende Ihres Programms die **Anzahl der Faltungen**, die zum Mond benötigt sind, als **Ganze Zahl** (`int`) gespeichert ist.
    - Definieren Sie eine Variable namens **`distanz_papier`**, in der die Distanz des gefaltenen Papiers hinterlegt ist.
    - Geben Sie ganz am Ende Ihres Programms mit `print` eine kurze Rückmeldung aus, wie viele Faltungen benötigt sind.
  • Dein geposteter Code hat eine interessante Syntax. Das mag für euch Profis nichts Spektakuläres zu sein, aber ich finde es bemerkenswert.
@Sirius3:
  • Zum Thema Variablenname:
    Meintest du das so:

    Code: Alles auswählen

    def umrechnung_km_in_mm(mm):
        mm *= 1000 * 100 * 10
        return mm
    
    Oder so:

    Code: Alles auswählen

    def umrechnung_km_in_mm(km):
        mm = km * 1000 * 100 * 10
        return mm
        
    Oder ganz anders?
  • Ja, ist wohl eine Konstante, wobei, wenn man etwas "erweitert" denkt, dass sich ja die Papier-Dicke im Vorhinnein (z.B. durch input() oder so...) auch ändern kann.
@DeaD_EyE
Danke für den Hinweis, aber die Verwendung von import BibliothekXYZ ist noch nicht vorgesehen.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Ja, die letzte Variante ist die logischste.
Zu deinem Programm: Variablen führt man erst dann ein, wenn man sie braucht, also direkt vor der Schleife, und nicht weit entfernt irgendwo am Anfang der Datei. Das würde auch gar nicht gehen, wenn das Programm ordentlich in Funktionen stehen würde. Das if ist immer noch seltsam bis falsch und nun auch gar nicht mehr nötig. Runden sollte man nicht mitten in einer Rechnung! Normalerweise nur bei der Ausgabe und dort per Formatangabe.
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Code: Alles auswählen

# V4

PAPIERDICKE_IN_MM = 0.1
ENTFERNUNG_ERDE_MOND_IN_KM = 384400

def umrechnung_km_in_mm(km):
    mm = km * 1000 * 100 * 10
    return mm

faltungen = 0
distanz_papier = PAPIERDICKE_IN_MM

while distanz_papier < umrechnung_km_in_mm(ENTFERNUNG_ERDE_MOND_IN_KM):
    # print(f'Vor der Faltung {faltungen+1} ist das Papier {distanz_papier}mm breit')
    distanz_papier = distanz_papier * 2
    faltungen += 1
    # print(f'Nach der Faltung {faltungen} ist das Papier {distanz_papier}mm breit')
    # print('---------------------------------------------------------------------------')

print(f'Es sind {faltungen} Faltungen nötig.')
Uff...die Verzweigung hat mich schon lange im Code gestört.
Riesen Dank für deine/eure Mühen.
Antworten