Frage

Ich scheine viel Präzision mit Schwimmern zu verlieren.

Zum Beispiel brauche ich eine Matrix zu lösen:

4.0x -2.0y 1.0z =11.0
1.0x +5.0y -3.0z =-6.0
2.0x +2.0y +5.0z =7.0

Dies ist der Code, den ich die Matrix aus einer Textdatei importieren verwenden:

f = open('gauss.dat')
lines =  f.readlines()
f.close()

j=0
for line in lines:
    bits = string.split(line, ',')
    s=[]
    for i in range(len(bits)):
        if (i!= len(bits)-1):
            s.append(float(bits[i]))
            #print s[i]
    b.append(s)
    y.append(float(bits[len(bits)-1]))

muss ich mit Gauß-Seidel- lösen, damit ich die Gleichungen für x neu anordnen müssen, y und z:

x=(11+2y-1z)/4
y=(-6-x+3z)/5
z=(7-2x-2y)/7

Hier ist der Code, den ich die Gleichungen neu anordnen verwenden. b ist eine Matrix von Koeffizienten und y ist die Antwort Vektor:

def equations(b,y):
    i=0
    eqn=[]
    row=[]
    while(i<len(b)):
        j=0
        row=[]
        while(j<len(b)):
            if(i==j):
                row.append(y[i]/b[i][i])
            else:
                row.append(-b[i][j]/b[i][i])
            j=j+1
        eqn.append(row)
        i=i+1
    return eqn

Allerdings sind die Antworten, die ich zurück sind nicht präzise auf die Dezimalstelle.

Zum Beispiel auf die zweite Gleichung von oben neu anordnen, soll ich:

y=-1.2-.2x+.6z

Was ich erhalte, ist:

y=-1.2-0.20000000000000001x+0.59999999999999998z

Dies könnte nicht wie ein großes Problem erscheinen, aber wenn Sie die Nummer auf eine sehr hohe Leistung zu erhöhen ist der Fehler recht groß. Gibt es eine Möglichkeit, um dieses? Ich versuchte, die Decimal Klasse, aber es funktioniert nicht gut mit Kräften (das heißt, Decimal(x)**2).

Irgendwelche Ideen?

War es hilfreich?

Lösung

Ich bin nicht vertraut genug mit der Dezimal-Klasse um Ihnen zu helfen, aber das Problem ist aufgrund der Tatsache, dass Dezimalbrüchen oft nicht genau binär dargestellt werden, so was Sie sehen die bestmögliche Annäherung ist; es gibt keine Möglichkeit, dieses Problem zu vermeiden, ohne eine spezielle Klasse mit (wie Dezimal, wahrscheinlich).

EDIT: Was ist mit dem Dezimalsystem Klasse funktioniert nicht richtig für Sie? Solange ich mit einem String beginnen, anstatt ein Schwimmer, scheinen Kräfte gut zu funktionieren.

>>> import decimal
>>> print(decimal.Decimal("1.2") ** 2)
1.44

Die Modul Dokumentation die Notwendigkeit und die Verwendung von decimal.Decimal ziemlich klar erklärt, sollten Sie Check it out, wenn Sie noch nicht haben.

Andere Tipps

IEEE-Gleitkomma ist binär, nicht dezimal. Es gibt keine feste Länge Binärbruch die genau 0,1 oder irgendein Vielfaches davon. Es ist eine sich wiederholende Fraktion, wie 1/3 in Dezimal.

Bitte lesen Sie Was jeder Informatiker wissen sollten über Gleitkommaarithmetik

Andere Optionen neben einer Dezimal-Klasse

  • mit Common Lisp oder Python 2.6 oder ein andere Sprache mit genauen rationals

  • das Doppel Umwandlung schließen rationals, zB frap

Als erstes kann die Eingabe viel vereinfacht werden. Sie brauchen nicht, eine Datei zu lesen und zu analysieren. Sie können einfach Ihre Objekte in Python Notation deklarieren. Eval die Datei.

b = [
    [4.0, -2.0,  1.0],
    [1.0, +5.0, -3.0],
    [2.0, +2.0, +5.0],
]
y = [ 11.0, -6.0, 7.0 ]

Zweitens y = -1.2-0.20000000000000001x + 0.59999999999999998z ist nicht ungewöhnlich. Es gibt keine genaue Darstellung in binärer Schreibweise für 0,2 oder 0,6. Folglich zeigten die Werte sind die Dezimalzahl Annäherungen der ursprünglichen nicht Darstellungen exakt. Das ist wahr für fast jede Art von Floating-Point-Prozessor ist.

Sie können die Python versuchen 2.6 Fraktionen Modul. Es ist ein älteres rational Paket, das helfen könnte.

Ja, Aufhellen Gleitkommazahlen auf Potenzen erhöht die Fehler. Folglich müssen Sie sicher sein, mit den am weitesten rechts stehenden Positionen des Gleitkommazahl zu vermeiden, da diese Bits hauptsächlich Rauschen sind.

Wenn Gleitkommazahlen anzeigt, müssen Sie um sie entsprechend Bits sehen die Geräusche zu vermeiden.

>>> a
0.20000000000000001
>>> "%.4f" % (a,)
'0.2000'

Ich würde warnen vor dem Komma Modul für Aufgaben wie diese. Sein Zweck ist es wirklich mehr zu tun mit dem realen Welt Dezimalzahlen (z. B. passende menschliche Buchhaltung Praktiken), mit endlicher Genauigkeit, nicht exakt Präzisionsberechnungen durchführt. Es gibt Zahlen nicht genau darstellbare in dezimal so wie es in binär ist, und in Dezimalarithmetik Durchführung ist auch viel langsamer als Alternativen.

Stattdessen, wenn Sie exakte Ergebnisse wollen, sollten Sie rationale Arithmetik verwenden. Diese werden für Zahlen als Zähler / denomentator Paar, so kann genau alle rationalen Zahlen darstellen. Wenn Sie nur die Multiplikation und Division mit (statt Operationen wie Quadratwurzeln, die in irrationalen Zahlen führen können), werden Sie nie Präzision verlieren.

Wie andere erwähnt haben, Python 2.6 hat eine eingebaute in rationaler Art, obwohl beachten Sie, dass dies nicht wirklich eine hoch performante Implementierung - für Geschwindigkeit sind Sie besser Bibliotheken wie gmpy . Nur Ihre Anrufe ersetzen () zu schweben gmpy.mpq () und der Code sollte nun exakte Ergebnisse geben (obwohl Sie können die Ergebnisse als Schwimmer für die Anzeige formatiert werden).

Hier ist eine etwas aufgeräumt Version des Codes eine Matrix zu laden, die gmpy rationals verwenden statt:

def read_matrix(f):
    b,y = [], []
    for line in f:
        bits = line.split(",")
        b.append( map(gmpy.mpq, bits[:-1]) )
        y.append(gmpy.mpq(bits[-1]))
    return b,y

Es ist keine Antwort auf Ihre Frage, aber miteinander verbundene:

#!/usr/bin/env python
from numpy import abs, dot, loadtxt, max
from numpy.linalg import solve

data = loadtxt('gauss.dat', delimiter=',')
a, b = data[:,:-1], data[:,-1:]
x = solve(a, b) # here you may use any method you like instead of `solve`
print(x)
print(max(abs((dot(a, x) - b) / b))) # check solution

Beispiel:

$ cat gauss.dat
4.0, 2.0, 1.0, 11.0
1.0, 5.0, 3.0, 6.0 
2.0, 2.0, 5.0, 7.0

$ python loadtxt_example.py
[[ 2.4]
 [ 0.6]
 [ 0.2]]
0.0

Siehe auch Was ein einfaches Beispiel für Gleitkomma-Fehler , hier auf SO, das hat einige Antworten. Der, den ich geben tatsächlich nutzt Python als Beispiel Sprache ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top