ho pensato una soluzione piuttosto elegante (IMHO), quindi non posso resistere a pubblicarlo:
from bisect import bisect_left
class Interpolate(object):
def __init__(self, x_list, y_list):
if any(y - x <= 0 for x, y in zip(x_list, x_list[1:])):
raise ValueError("x_list must be in strictly ascending order!")
x_list = self.x_list = map(float, x_list)
y_list = self.y_list = map(float, y_list)
intervals = zip(x_list, x_list[1:], y_list, y_list[1:])
self.slopes = [(y2 - y1)/(x2 - x1) for x1, x2, y1, y2 in intervals]
def __getitem__(self, x):
i = bisect_left(self.x_list, x) - 1
return self.y_list[i] + self.slopes[i] * (x - self.x_list[i])
I mappa per float
in modo che la divisione intera (pitone < = 2.7), non entreranno in gioco e rovina le cose se x1
, x2
, y1
e y2
sono tutti numeri interi per alcuni iterval.
In __getitem__
sto approfittando del fatto che self.x_list è ordinato in ordine crescente utilizzando bisect_left
a (molto) di trovare rapidamente l'indice del più grande elemento più piccolo di x
in self.x_list
.
Utilizzare la classe in questo modo:
i = Interpolate([1, 2.5, 3.4, 5.8, 6], [2, 4, 5.8, 4.3, 4])
# Get the interpolated value at x = 4:
y = i[4]
non ho affrontato le condizioni di confine a tutti qui, per semplicità. Così com'è, i[x]
per x < 1
funzionerà come se la linea da (2,5, 4) a (1, 2) fosse stata estesa a meno infinito, mentre i[x]
per x == 1
o x > 6
aumenterà un IndexError
. Meglio sarebbe sollevare un IndexError in tutti i casi, ma questo è lasciato come esercizio per il lettore.:)
Questo è ... non è facile. Che cosa hai provato? – zellio
-1 come troppo generico. non capisci come programmare, o come fare l'algoritmo in python ?? – steabert
Benché sia un nuovo studente, mi sono buttato nel profondo, per così dire. Stavo pensando di usare le istruzioni 'for' o 'if' in un algoritmo. Quindi tra numerose gamme di x. – Helpless