L'approccio numerico è probabilmente la migliore per voi, ma se siete interessati a l'approccio analitico, è molto semplice per i derivati:
Diamo dichiarare ciò che una funzione è (che supponiamo di avere le funzioni con un parametro):
protocol Function {
func evaluate(value: Double) -> Double
func derivative() -> Function
}
Ora cerchiamo di dichiarare funzioni di base:
struct Constant : Function {
let constant: Double
func evaluate(value: Double) -> Double {
return constant
}
func derivative() -> Function {
return Constant(constant: 0)
}
}
struct Parameter : Function {
func evaluate(value: Double) -> Double {
return value
}
func derivative() -> Function {
return Constant(constant: 1)
}
}
struct Negate : Function {
let operand: Function
func evaluate(value: Double) -> Double {
return -operand.evaluate(value)
}
func derivative() -> Function {
return Negate(operand: operand.derivative())
}
}
struct Add : Function {
let operand1: Function
let operand2: Function
func evaluate(value: Double) -> Double {
return operand1.evaluate(value) + operand2.evaluate(value)
}
func derivative() -> Function {
return Add(operand1: operand1.derivative(), operand2: operand2.derivative())
}
}
struct Multiply : Function {
let operand1: Function
let operand2: Function
func evaluate(value: Double) -> Double {
return operand1.evaluate(value) * operand2.evaluate(value)
}
func derivative() -> Function {
// f'(x) * g(x) + f(x) * g'(x)
return Add(
operand1: Multiply(operand1: operand1.derivative(), operand2: operand2),
operand2: Multiply(operand1: operand1, operand2: operand2.derivative())
)
}
}
struct Divide : Function {
let operand1: Function
let operand2: Function
func evaluate(value: Double) -> Double {
return operand1.evaluate(value)/operand2.evaluate(value)
}
func derivative() -> Function {
// (f'(x) * g(x) - f(x) * g'(x))/(g(x))^2
return Divide(
operand1: Add(
operand1: Multiply(operand1: operand1.derivative(), operand2: operand2),
operand2: Negate(operand: Multiply(operand1: operand1, operand2: operand2.derivative()))
),
operand2: Power(operand1: operand2, operand2: Constant(constant: 2))
)
}
}
struct Exponential : Function {
let operand: Function
func evaluate(value: Double) -> Double {
return exp(operand.evaluate(value))
}
func derivative() -> Function {
return Multiply(
operand1: Exponential(operand: operand),
operand2: operand.derivative()
)
}
}
struct NaturalLogarithm : Function {
let operand: Function
func evaluate(value: Double) -> Double {
return log(operand.evaluate(value))
}
func derivative() -> Function {
return Multiply(
operand1: Divide(operand1: Constant(constant: 1), operand2: operand),
operand2: operand.derivative()
)
}
}
struct Power : Function {
let operand1: Function
let operand2: Function
func evaluate(value: Double) -> Double {
return pow(operand1.evaluate(value), operand2.evaluate(value))
}
func derivative() -> Function {
// x^y = e^ln (x^y) = e^(y * ln x)
let powerFn = Exponential(
operand: Multiply (
operand1: operand2,
operand2: NaturalLogarithm(operand: operand1)
)
)
return powerFn.derivative()
}
}
struct Sin: Function {
let operand: Function
func evaluate(value: Double) -> Double {
return sin(operand.evaluate(value))
}
func derivative() -> Function {
// cos(f(x)) * f'(x)
return Multiply(operand1: Cos(operand: operand), operand2: operand.derivative())
}
}
struct Cos: Function {
let operand: Function
func evaluate(value: Double) -> Double {
return cos(operand.evaluate(value))
}
func derivative() -> Function {
// - sin(f(x)) * f'(x)
return Multiply(operand1: Negate(operand: Sin(operand: operand)), operand2: operand.derivative())
}
}
La dichiarazione di una funzione non è molto bello:
let xSquared = Power(operand1: Parameter(), operand2: Constant(constant: 2))
ma possiamo evaluate
con ricorsione:
print(xSquared.evaluate(15)) // f(15) = 225
print(xSquared.derivative().evaluate(15)) // f'(15) = 2 * 15 = 30
print(xSquared.derivative().derivative().evaluate(15)) // f''(15) = 2
print(xSquared.derivative().derivative().derivative().evaluate(15)) // f'''(15) = 0
Fase 1: Trovare un modo per rappresentare la funzione originale nel codice. Passo 2: assicurati di conoscere tutte le regole di calcolo necessarie per prendere la derivata di * qualsiasi * funzione. Passaggio 3: Se si ottiene il passaggio 1 e il passaggio 2 verso il basso e si è ancora bloccati ... forse si potrebbe tornare a Stack Overflow. – nhgrif
Cosa hai provato? Inoltre, vuoi veramente calcolare la derivata effettiva o semplicemente approssimarla usando quell'algoritmo limite con un valore molto piccolo di 'h'? Quest'ultimo è banale. Il primo è non banale. – Rob
Idealmente, la derivata effettiva sarebbe calcolata. L'algoritmo limite sarebbe molto più semplice. – modesitt