Ich schreibe gerade eine Klasse, die mathematische Funktionen analisiert. Methoden: zeros (für Nullstellen), extrema (für Extremas; Funktion, die von den Funktionen Maxima und Minima aufgerufen werden), derivative (Steigung an der x-Koordinate x) und natürlich __getitem__ für die y-Werte bei übergebenem x-Wert.
Alles läuft sehr gut, ist relativ schnell und findet es sehr präzise heraus, zumindest werden die Nullstellen alle berechnet.
Bei der extremafunktion ist das anders.
Ich nehme an, es ist die Ungenauigkeit von float, aber auf jeden Fall gibt es alleine fast 100 Ausgaben, an dem es mir an der x koordinate -4,85 eine Steigung von Null angibt
Meiner Meinung ist es sogar eher die Funktion, die die Steigung errechnet! Diese scheint einfach viel zu oft eine Steigung von null zu berechnen, da es nicht die vielen Nachkommastellen händeln kann.g.extrema(-5,5)
-4.8562478880000004, -4.8562478780000005, -4.8562478720000009, -4.8562478710000008, -4.8562478700000007, -4.8562478690000006, -4.8562478670000004, -4.8562478659749999, -4.8562478659650008, -4.8562478659300004, -4.8562478659200004, -4.8562478659000003, -4.8562478658900003, -4.8562478658800003, -4.8562478658600003, -4.8562478658500003, -4.8562478658400003, -4.8562478658300003, -4.8562478658200003, -4.8562478658100003, -4.8562478658000003, -4.8562478657900003, -4.8562478657800003, -4.8562478657700003, -4.8562478657600003, -4.8562478657500003, -4.8562478657400003, -4.8562478657300003, -4.8562478657200003, -4.8562478657100003, -4.8562478657000003, -4.8562478656900003, -4.8562478656800003, -4.8562478656700003, -4.8562478656600003, -4.8562478656500003, -4.8562478656400003, -4.8562478656300003, -4.8562478656200003, -4.8562478656100003, -4.8562478656000003, -4.8562478655900003, -4.8562478655800003, -4.8562478655700003, -4.8562478655600003, -4.8562478655500003, -4.8562478655400003, -4.8562478655300003, -4.8562478655200003, -4.8562478655100003, -4.8562478655000003, -4.8562478654900003, -4.8562478654700003, -4.8562478654600003, -4.8562478654500003, -4.8562478654400003, -4.8562478654300003, -4.8562478654100003, -4.8562478654000003, -4.8562478653900003, -4.8562478653800003, -4.8562478653700003, -4.8562478653600003, -4.8562478653500003, -4.8562478653300003, -4.8562478653100003, -4.8562478652900003, -4.8562478652700003, -4.8562478652500003, -4.8562478652300003, -4.8562478652050007, -4.8562478651949998, -4.8562478651650007, -4.8562478651549998, -4.8562478651250007, -4.8562478651100003, -4.8562478650900003, -4.8562478650700003, -4.8562478650500003, -4.8562478650300003, -4.8562478650100003, -4.8562478640000002, -4.856247862, -4.8562478610000008, -4.8562478590000007, -4.8562478580000006, -4.8562478560000004, -4.8562478550000003, -4.8562478539700003, -4.8562478539500002, -4.8562478539300002, -4.8562478539200002, -4.8562478539100002, -4.8562478539000002, -4.8562478538900002, -4.8562478538800002, -4.8562478538600002, -4.8562478538400002, -4.8562478537700002, -4.8562478537500002, -4.8562478537300002, -4.8562478537200002, -4.8562478537100002, -4.8562478537000002, -4.8562478536800002, -4.8562478536600002, -4.8562478536500002, -4.8562478536400002, -4.8562478535900002, -4.8562478535700002, -4.8562478535300002, -4.8562478535200002, -4.8562478535100002, -4.8562478535000002, -4.8562478534900002, -4.8562478534800002, -4.8562478534700002, -4.8562478534600002, -4.8562478534500002, -4.8562478534400002, -4.8562478534000002, -4.8562478533300002, -4.8562478533200002, -4.8562478533100002, -4.8562478532900002, -4.8562478532800002, -4.8562478532700002, -4.8562478532600002, -4.8562478532400002, -4.8562478532049997, -4.8562478531950006, -4.8562478531500002, -4.8562478531300002, -4.8562478531200002, -4.8562478531100002, -4.8562478530700002, -4.8562478530400002, -4.8562478530049997, -4.8562478529800002, -4.8562478529600002, -4.8562478529500002, -4.8562478529300002, -4.8562478529200002, -4.8562478529100002, -4.8562478528700002, -4.8562478528000002, -4.8562478527900002, -4.8562478527800002, -4.8562478527600001, -4.8562478527500001, -4.8562478527400001, -4.8562478527300001, -4.8562478527200001, -4.8562478527100001, -4.8562478526000001, -4.8562478525900001, -4.8562478525800001, -4.8562478525700001, -4.8562478525600001, -4.8562478525500001, -4.8562478525300001, -4.8562478525200001, -4.8562478525100001, -4.8562478524400001, -4.8562478524000001, -4.8562478523900001, -4.8562478523800001, -4.8562478523700001, -4.8562478523500001, -4.8562478523300001, -4.8562478523150006, -4.8562478523049997, -4.8562478522600001, -4.8562478522400001, -4.8562478522200001, -4.8562478521800001, -4.8562478521500001, -4.8562478521150005, -4.8562478521000001, -4.8562478520900001, -4.8562478520700001, -4.8562478520600001, -4.8562478520400001, -4.8562478520300001, -4.8562478520200001, -4.8562478500000008, -4.8562478490000007, -4.8562478440000003]
Habe im Internet Das Modul decimal mit der Klasse decimal gefunden, aber das hat auch nicht geholfen.
Hat jemand eine andere Idee dazu?
Mein Quellcode:
Code: Alles auswählen
from math import*
class Function(object):
def __init__(self, func):
self.func = str(func)
self._accuracy = 1e-10
def __getitem__(self, x):
try:
res = eval(self.func)
except:
res = "ERROR"
return res
def zeros(self, a, b):
intervals = 100
step = float(b-a) / intervals
zeros = []
for intv in range(1, intervals):
x1 = a + intv * step
x2 = a + (intv+1) * step
if self[x1] == 0:
zeros.append(x1)
elif self[x2] == 0:
zeros.append(x2)
elif (self[x1]<0 and self[x2]>0) or (self[x1]>0 and self[x2]<0):
if abs(x1-x2) < self._accuracy:
zeros += [(x1+x2)/2]
else:
zeros += self.zeros(x1,x2)
return zeros
def intersect(self, function):
pass
def derivative(self, x):
delta_x = self._accuracy
return (self[x + delta_x] - self[x]) / delta_x
def extrema(self, a, b):
intervals = 100
step = float(b-a) / intervals
extrema = []
for intv in range(1, intervals):
x1 = a + intv * step
x2 = a + (intv+1) * step
if self.derivative(x1) == 0 and len(extrema) and extrema[-1] != x1:
extrema.append(x1)
elif self.derivative(x2) == 0:
extrema.append(x2)
elif (self.derivative(x1) < 0 and self.derivative(x2) > 0) or (self.derivative(x1) > 0 and self.derivative(x2) < 0):
if abs(x1-x2) < self._accuracy:
extrema += [(x1+x2)/2]
else:
extrema += self.extrema(x1,x2)
return extrema
def maxima(self, a, b):
maxima = []
extrema = self.extrema(a,b)
for i in range(len(extrema[:-1])):
wert = self[(extrema[i] + extrema[i+1]) / 2]
if wert > 0:
maxima.append(extrema[i])
return maxima
def accuracy(self, value = None):
if value != None:
self._accuracy = value
else:
return self._accuracy
def __repr__(self):
return self.func
__str__ = __repr__
if __name__=="__main__":
f = Function("(x-3)**2-3")
g = Function("x*sin(x**2)+1")