Problem mit round() bzw decimal()

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
Irmchen
User
Beiträge: 8
Registriert: Dienstag 11. November 2008, 14:19

Hallo!
Ich suche dringend nach einer Lösung für das leidige Gleitkommazahlen-Ungenauigkeitsproblem. Nun habe ich gelesen, dass es sich mit round() bzw. auch mit decimal() lösen lässt. Mit beiden habe ich jedoch Probleme.
Zum Beispiel liefert mir round(4.123456,4) 4.1234999999999999 und nicht wie erhofft 4.1235. Dadurch kommt es ja wieder zu kleinen, aber evtl . entscheidenden Ungenauigkeiten.
Bei decimal() lassen sich ja nur "reine" Zahlen umwandeln. Wäre im oben genanten Beispiel auch super. Jedoch muss ich lange Formeln verwenden, deren Ergebnisse ich gerne sehr genau hätte. Und das wiederum wär dann ja nicht möglich, oder?!
Weiß nich, ob meine Fehler im Programm überhaupt an diesen kleinen Ungenauigkeiten liegen können, aber so oder so wär es schön zu wissen :)

Vielen Dank schonmal für eure Hilfe!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Suchst du eventuell ``"%.4f" % 4.123456``?

Wenn du genaue Rechnungen haben willst, solltest du aber mit ``Decimal`` rechnen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Irmchen
User
Beiträge: 8
Registriert: Dienstag 11. November 2008, 14:19

Habe mir auch gedacht, dass decimal sinnvoller ist. Aber wie gesagt habe ich keine "reinen" Zahlen, die ich umwandeln will, sondern Ergebnisse aus Formeln.
Also als einfachstes Beispiel Decimal("a+b") mit a=3 und b=a+1, oder so ähnlich. Und das scheint nicht zu funktionieren ... :(
Da diese Formeln in einer for-Schleife stehen und zum weiterrechnen benutzt werden müssen, hab ich Angst, dass die Ungenauigkeit der floats meine ganze Rechnung versauen.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

In welchem Bereich rechnest Du denn? Was sind das für Formeln und welche End-Genauigkeit möchtest Du haben?

Gruß,
Christian
Irmchen
User
Beiträge: 8
Registriert: Dienstag 11. November 2008, 14:19

Ich rechne im Bereich Biologie und versuche Wachstumsdynamiken von Bakterien darzustellen. Es sind also logistische Gleichungen.
Mir geht's darum, dass z.B. mit einer Übertragungsrate von 1 und nicht 1.000000001 gerechnet wird.
Irmchen
User
Beiträge: 8
Registriert: Dienstag 11. November 2008, 14:19

Habe gerade auch herausgefunden, dass mein obigen Beispiel funktioniert, wenn ich decimal(a+b), also ohne " eingebe. Funktioniert bei meinen Monsterformeln leider trotzdem nicht.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Mit anderen Worten eine Differentialgleichung 1. Grades.

1. Kannst Du die Genauigkeit setzen, z. B. so:

Code: Alles auswählen

precission = 1
rate = 1.000000001
rate = round(rate, precission)
2. Welche Parameter fliessen ein und wie pflanzen sich Fehler fort? Welche Fehler verbinden sich mit diesen Parametern? Das führt uns zum folgenden Punkt:
3. Kannst Du Dich fragen, welche experimentelle Genauigkeit Du erreichen kannst. Tatsächlich 10e-9? Würde mich wundern ;-).

Sorry, wenn ich so oberlehrerhaft klinge, aber so was habe ich Studenten immer gefragt, wenn sie als Resultat eine ewig lange Nachkommazahl geliefert haben ;-).

HTH
Chrsitian

PS Kennst Du PyCeS? Die Software implementiert einige Lösungswege für diese Art von Problemen. Und die Jungs sind echt freundlich, wenn Du um Hilfe fragst - einige können sogar Deutsch.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Irmchen hat geschrieben:Monsterformeln
Lass doch mal sehen - ich habe vielleicht heute Abend etwas Zeit mich damit zu beschäftigen - sonst am Montag, falls sonst niemand das Problem erläutern kann.

Gruß,
Christian
Irmchen
User
Beiträge: 8
Registriert: Dienstag 11. November 2008, 14:19

Ausschnitte aus meinem Problemkind:

Code: Alles auswählen

ciA=0.5
tA=1
ciB=0.5
tB=1
pA=zeros(101)
pB=zeros(101)
pAB=zeros(101)
pU=zeros(101)

for i in range (100):
    pA[0]=0.3 # Wert egal
    pB[0]=0.0 # Wert egal
    pAB[0]=0.7 # Wert egal
    pU[0]=0

    pU[i+1]=(pA[i]**2)*((1-tA)*(1-ciA))+pA[i]*pB[i]*((1-tA)*(1-ciB)+(1-tB)*(1-ciA))+pA[i]*(1-pA[i]-pB[i]-pAB[i])*((1-tA)+(1-ciA))+(pB[i]**2)*((1-tB)*(1-ciB))+pB[i]*(1-pA[i]-pB[i]-pAB[i])*((1-tB)+(1-ciB))+(1-pA[i]-pB[i]-pAB[i])**2+pAB[i]*pA[i]*((1-tA)*(1-tB)*(1-ciA)+(1-tA)*(1-ciA)*(1-ciB))+pAB[i]*pB[i]*((1-tA)*(1-tB)*(1-ciB)+(1-ciB)*(1-ciA)*(1-tB))+pAB[i]*(1-pA[i]-pB[i]-pAB[i])*((1-tA)*(1-tB)+(1-ciA)*(1-ciB))+((pAB[i])**2)*((1-tA)*(1-tB)*(1-ciA)*(1-ciB))/(pA[i]*ciA*(pA[i]*tA-1)+pB[i]*ciB*(pB[i]*tB-1)+pA[i]*pB[i]*tA*ciB+pA[i]*pAB[i]*(2*tA*ciA+tA*ciB-tA*ciA*ciB)+pB[i]*pAB[i]*ciB*(2*tB+tA-tA*tB-tB*ciA)+pAB[i]*(-ciB+ciA+ciA*ciB)+((pAB[i])**2)*(tB*ciB-tB*ciA*ciB+tA*ciB+tA*ciA-tA*ciA*ciB-tA*tB*ciB+tA*tB*ciA*ciB)+1)

Ähnliche Formeln gibt's dann auch noch für pA, pB und pAB (Anteil der Bakterien"arten" in Population).
Hab diese Formel extra nicht vereinfacht um zu sehen, dass wenn tA und tB (Übertragungsraten) 1 sind, für pU immer 0 rauskommen muss, da der Zähler 0 ist!! Aber natürlich ist dies nicht der Fall, weswegen ich die Schuld einfach liebend gern auf die floats schieben würde :)[/code]
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

1. gibt es für solche Code-Monster einen [/quote]pastbin, z.B. den im Link.
2. bitte lager Deinen Code dahin aus, weil sonst der Browser eine unheimlich breite Seite sieht und das macht es allen anderem im Forum schwer Dir zu antworten, weil man den Text kaum gescheit lesen kann.
3.
Irmchen hat geschrieben:Hab diese Formel extra nicht vereinfacht um zu sehen, ...)
Stimmt das nicht, weil man diese Formel nicht vereinfachen kann. Das zumindest sagt mir mein Computer Algebra System.
4. Musst Du Fehler machen, wenn Du Deinen Code nicht dokumentierst: Da kann niemand sonst durchblicken und in ein paar Wochen Du auch nicht - unter Garantie.
5. Musst Du Fehler machen, wenn Du solche Gleichungen so elendig lang schreibst - ich unterstelle hierbei, daß sich solche Gleichungen durchaus einfacher darstellen lassen (siehe Punkt 4). Das ist nur menschlich - die Lösung ist systematischer arbeiten (siehe Beispiel). Dazu gehört auch von einem einfachen Modell (wie im Beispiel auszugehen und das systematisch zu erweiteren - wenn es funktioniert)
6. Kannst Du sicher mehr Features von numpy und scipy nutzen, um Dir das Leben einfacher zu machen.
7. Ist Dein Problem mit Sicherheit nicht das der fehlenden Genauigkeit, da die Gleichung falsch ist - sie ergibt ja auch das falsche Ergebnis, wie Du selber feststellst.
8. Als Tipp: Wenn ich Deine Konstanten variiere, kommen ganz seltsame Größen raus. Ich würde ja fast wetten, daß die Gleichung falsch geklammert ist.

Ich möchte nicht so klingen, als würde ich Dich runtermachen wollen - ich stehe selbst oft genug wie der Ochs vorm Berg. Aber die Monsterformeln finde ich schon etwas provokant, denn in Ökologie kann ich mir kaum etwas monsterhaftes vorstellen. ;-)

Wenn Du zu dieser konkreten Formel Hilfe benötigst, gebe doch bitte eine präzise Fragestellung an. So, wie Du es selber am besten erklärt haben möchtest.

Gruß,
Christian

PS Einfaches Beispiel für logistisches Wachstum - den Code kann sicher vereinfachen, aber es ist als Startbeispiel gedacht, von dem aus man auch die Gleichung variieren kann.

Code: Alles auswählen

from __future__ import division
import numpy as np
import pylab 

# increment in time
dt = 1
# instantaneous growth rate constant
u = 0.1
# capacity
capacity = 1e3
# intitial population size
initial = 20

times = np.arange(0, 100, dt)
amount = np.array([])

for t in times:
    X = capacity * initial * np.e**(u * t) / \
        (capacity + initial * (np.e**(u * t) - 1))
    amount = np.append(amount, X)

pylab.plot(times, amount)
pylab.show()
Antworten