problem - schiefer wurf

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
Edwin Lock
User
Beiträge: 2
Registriert: Sonntag 6. März 2005, 18:21
Wohnort: Irgendwo am Niederrhein ;)

Ich bin dabei eine simulation eines kanonballs zu schreiben.
Das programm habe ich schon fertiggestellt, allerdings in casiobasic(für meinen taschenrechner).
Ich habe es in python 'übersetzt' aber bekomme jetzt immer komische ergebnisse...
das ist mein programm:
winkel=A
Zeitinsgesamt=T
Abschussstaerke(Velocity)=V
Höhe=H
Gravitationskraft=G
C=aerodynamische konstante (auch cd genannt)
Vc(kritische geschwindigkeit)=I
Luftdichte=Q
oberfläche der kugel=flaeche
Masse der Kugel=M
Zeitintervalle=E
____________________
x wert nach jedem Schritt=U
y wert nach jedem Schritt=W


Code: Alles auswählen

from math import *
def berechnung():
    listex=[]
    listey=[]
    
    T=0
    A=70
    A=radians(A)
    V=100
    H=1
    G=9.81
    C=0.45
    I=3.1
    Q=1.22
    flaeche=20
    M=30
    K=C*Q*flaeche/2*M
    E=0.001
    B=0
    Z=0
    D=0
    F=0
    N=V*cos(A)
    O=V*sin(A)
    U=0
    W=H
    while W>=0:
        if 2*sqrt(flaeche/pi)>V:
            r=1
        elif 2*sqrt(flaeche/pi)<V:
            r=0
        T+=E
        D=-K*V**2*cos(A)/2
        F=-G-K*V**2*sin(A)/2
        if r:
            D=-K*V**2*cos(A)
            F=-G-K*V*sin(A)
        U+=N*E
        W+=O*E
        N+=D*E
        O+=F*E
        V=sqrt(N**2+O**2)
        A=atan(O/N)
        listex.append(U)
        listey.append(W)
    print listex,listey


Ich hoffe ihr könnt helfen!
Wie gesagt, auch dem taschenrechner hat es geklappt... :/
Der einzige unterschied den ich mir vorstellen kann ist, dass die winkel anders verstanden werden in python....
Wenn es gebraucht wird kann ich noch das basicprogramm hier schreiben...

Edit (Leonidas): Code in Python-Tags gesetzt.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi Edwin,

Du beklagst Dich über "komische Ergebnisse"? Na, nimms mir nicht übel, aber Dein Code sieht auch komisch aus ...

Ein paar allgemeine Tipps:
- kommentiere Deinen Code
- Arbeite nicht mit so vielen, kryptischen Konstanten, die nur diese eine Funtion kennt: Das führt bei bei numerischen Code in größeren Programmen zu heillosem Durcheinander. Besser ist es einige, wenige Konstanten (wie e oder pi) global zu definieren, klar und beschreibend zu bennenen und den Rest u. U. objektorientiert zu lösen.

Zu Deinem Problem: Ja, es wäre nett mal den BASIC-Code zu sehen. Könntes es sein, daß Du in der while-Schleife noch etwas mit T machen willst?

Gruß,
Christian
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hallo Edwin Lock, willkommen im Forum!
Edwin Lock hat geschrieben:winkel=A
Zeitinsgesamt=T
Abschussstaerke(Velocity)=V
Höhe=H
Gravitationskraft=G
C=aerodynamische konstante (auch cd genannt)
Vc(kritische geschwindigkeit)=I
Luftdichte=Q
oberfläche der kugel=flaeche
Masse der Kugel=M
Zeitintervalle=E
Und warum nennst du die variablen nicht so? Wäre viel einfacher zu verstehen. Und es wäre besser wenn du keine * Imports machst, sondern import math und dann math.sqrt usw. nutzt (obwohl das bei einem Modul wie math gerade noch vertretbar ist).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Edwin Lock
User
Beiträge: 2
Registriert: Sonntag 6. März 2005, 18:21
Wohnort: Irgendwo am Niederrhein ;)

Ich hab grad gemerkt, dass nicht alles richtig angezeigt wurde.
Ich hab es jetzt nochmal in eine andere schriftart geändert.
Ich hoffe ihr könnt damit was anfangen!

Code: Alles auswählen

Green "BALLISTIC SIMULATOR"
Orange "==================="
AxesOff
Rad
0 -> T
"ANGLE°"? -> A	
A¤ -> A
"VELOCITY"? -> V
"HEIGHT"? -> H
"G (9.82)"? -> G
"AIR RESISTANCE [1/0]"? -> R
If R
Then "C (0.45)"? -> C
"Vc*d (3.1)"? -> I
"AIR DENSITY (1.22)"? -> Q
"AREA OF PROJECTILE"? -> @
"MASS OF PROJECTILE"? -> M
CQ@/2M -> K
IfEnd
"TIME STEP"? -> E
"STEP [1/0]"? -> S
Vsin A/G+sqrt(2H/G+(Vsin A)^2/G^2) -> L
ViewWindow 0,LVcos A+1,0,0,1.3((Vsin A)^2/2G+H),0
cos A<0 => ViewWindow LVcos A,0,0,0,1.3((Vsin A)^2/2G+H),0
0 -> B
0 -> Z
0 -> D
0 -> F
Vcos A -> N
Vsin A -> O
0 -> U
H -> W
Do
If R
Then I/2sqrt(@/pi)>V => 1 -> r
I/2sqrt(@/pi)<V = > 0 -> r
Not r => Text 55,70,"V>Vc"
r => Text 55,70,"V<Vc"
IfEnd
T+E -> T
If Not R
Then TVcos A -> U
H+TVsin A-GT^2/2 -> W
Else -KV^2cos A/2 -> D
-G-KV^2sin A/2 -> F
r => -KV^2cos A -> D
r => -G-KV^2sin A -> F
U+NE -> U
W+OE -> W
N+DE -> N
O+FE -> O
sqrt(N^2+O^2) -> V
arctan (O/N) -> A
IfEnd
PlotOn U,W
If T=E
Then Green PlotOn U,W
Text 1,1,"X="
Text 1,68,"Y="
Text 7,76,"T="
Text 7,1,"V="
IfEnd
Text 1,10,U
Text 1,78,W
Text 7,86,"      "
Text 7,86,T
Text 7,10,"             "
R => Text 7,10,V
Not R => Text 7,10,sqrt((Vcos A)^2+(Vsin A-GT)^2)
PlotOn 0,0
If S
Then Do
LpWhile Getkey <> 31
IfEnd
LpWhile W>0
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Sorry, aber auch der BASIC-Code hiflt mir nicht weiter: In beiden Fällen führst Du Variablen ein, die Du nicht weiter verwendest. Alles ist etwas kryptisch gehalten und entweder ich bin zu müde, um noch durchzusteigen, oder Deine Gleichungen stimmen nicht:
- BASIC hin oder her: In die Schleife gehört eine Abhängigkeit von der Zeit, die vergangen ist. Du beschreibst nur eine Abhängigkeit nach dem Zeitinkrement (siehe unten)!
- Deine wenn-dann-Beziehung kann ich auf sechs Zeilen (anstelle von zehn; oder mache ich doch einen Fehler?)

Code: Alles auswählen

if 2*sqrt(flaeche/pi)>V: 
      D=-K*V**2*cos(A) 
      F=-G-K*V*sin(A) 
else:  
      D=-K*V**2*cos(A)/2 
      F=-G-K*V**2*sin(A)/2 
Verstehen kann ich die Bedingung dann aber immer noch nicht: Da die Geschwindigkeit in DEINER Version der Schleife konstant ist, bleibt die Bedingung erfüllt oder nicht - und zwar in Abhängigkeit von der Kugel. Das ist physikalisch doch nicht sinnvoll, oder?.
- Python ermöglicht es Dir Deine Gleichung logisch hinzuschreiben und zu verketten. Davon würde ich Gebrauch machen: Bei Dir folgen Teile aufeinander, die nichts miteinander zu tun haben. Und Teile, die zusammengehören, sind auseinandergerissen. Das ist extrem verwirrend, Du willst schließlich Deine Programme noch übermorgen lesen können, oder?

Ich habe mal ein bißchen mit den Gleichungen gespielt und mir ist aufgefallen, daß man höllisch aufpassen muß, wie man das zeitliche Inkrement setzt, denn Differenzialgleichungen (auf die willst Du doch hinaus, nicht wahr?) sind so nicht numerisch stabil. Soll heißen, daß Du z. B. leicht unterschiedliche Weiten bekommen kannst, je nachdem ob E = 0.1 oder 0.001 ist. Andere Gründe für numerische Instabilität sind ebenfalls möglich. Vielleicht möchtest Du Dir mal scipy anschauen? Damit kann man ziemlich gut und exakt integrieren - das könnte hier das Leben einfacher machen.

Weißt Du wie ich solch ein Problem angehen würde: Die Gleichungen auf ein Blatt schreiben und in logische Schritte zerlegen - erst dann coden. Und dann so deskriptive Variablennamen wie möglich verwenden, z. B. "sigma" statt "s". Und schließlich lieber ein paar Klammern zuviel als zu wenig, das macht den Code lesbarer. Zusammen mit ein paar "überflüssigen" Leerzeichen (auf die Du fast völlig verzichtest), kann man den Code dann ganz leicht lesen und debuggen. Ggf. möchtest Du die mathematischen Funktion direkt in Python ausdrücken?

Gruß,
Christian

PS Vielleicht fällt mir morgen ja noch was ein ...
BlackJack

Das mit den nichtssagenden Variablennamen wurde ja schon gesagt. Ist natürlich soweit verständlich, als das man in einem Taschenrechner normalerweise jedes Byte zweimal umdreht bevor man es ver(sch)wendet. Vielleicht sind die Namen dort ja auch auf ein einziges Zeichen beschränkt!?

Es gibt auf jeden Fall zuviele Variablennamen. `T` macht nichts sinvolles. `B`, `I`, und `Z` werden nicht benutzt -- `I` sollte aber benutzt werden! Brauchst Du wirklich `H` und `W`?

Mal angenommen der Code würde funktionieren, dann wäre er unnötig komplex. Zum Beispiel liesse sich folgendes vereinfachen (ähnliches hat CM schon vorgschlagen):

Code: Alles auswählen

        if 2*sqrt(flaeche/pi)>V: 
            r=1 
        elif 2*sqrt(flaeche/pi)<V: 
            r=0 
        T+=E 
        D=-K*V**2*cos(A)/2 
        F=-G-K*V**2*sin(A)/2 
        if r: 
            D=-K*V**2*cos(A) 
            F=-G-K*V*sin(A)
        
        # wird zu:
        
        D = -K * V**2 * cos(A) 
        F = -G - K * V**2 * sin(A) 
        if 2 * sqrt(flaeche / pi) < V: 
            D /= 2 
            F /= 2
Womit dann auch gleich ein Fehler verschwunden sein dürfte. Du solltest das ganze wirklich nochmal auf Flüchtigkeitsfehler überprüfen.

Noch ein wenig kosmetisches: Die Werte, die dein BASIC-Programm vom Anwender erfragt, eignen sich prima als Parameter für die Funktion.

Die Ergebniswerte gehören semantisch zusammen und sollten deshalb besser in einer Liste als Tupel von x/y-Koordinaten gespeichert werden, statt auf zwei Listen verteilt zu werden.

Wenn man dazu irgendwann mal ein Animationsprogramm schreibt, oder aus anderen Gründen die Werte alle der Reihe nach benötigt aber nicht alle auf einmal, dann würde es sich anbieten eine Generatorfunktion daraus zu machen. Aber das ist für den Anfang vielleicht erstmal zuviel des Guten.
Antworten