swift 中的微分函数?
Derivative function in swift?
我想为我的应用程序的一部分创建一个函数,该函数 return 是函数在某个点的导数。显然,这是极限的正式定义。
但是什么样的函数能够return函数在swift中的一点的导数呢? swift 中的自动微分有什么想法吗?
不要试图重新发明轮子。数值微分(通常是数值分析)是一个很大的话题(有许多可能的解决方案 * 没有完美的解决方案),比你我都聪明得多的人已经提出了解决方案。除非您真的对所有不同的数值微分算法(它们的权衡、实现和优化)感兴趣,否则我建议您走另一条路。你说你用的是Swift?为什么不切换到 Objective-C(我假设您正在编写 iOS 或 OSX 应用程序)。如果这样做,您可以调出 GNU Scientific Library(这是一个 C、C++ 库)。也许你可以直接从 Swift 调用 c/c++ 代码?肯定是 IDK。
如果你真的想要,你可以看看他们的代码,看看他们是如何实现数值微分的解决方案的(不过,除非你准备好解决一些繁重的数学问题,否则我不会这样做)。
implementing the derivative in C/C++ * 你可以尝试使用它(我怀疑它是否非常可靠)。如果您需要精度和速度,我怀疑您是否也想在 Swift 中执行此操作。
这是一个基于上面公式的简单数值方法。您可以对此进行改进:
derivativeOf
采用函数 fn
和 x 坐标 x
和 returns fn
在 [=14= 处的导数的数值逼近]:
func derivativeOf(fn: (Double)->Double, atX x: Double) -> Double {
let h = 0.0000001
return (fn(x + h) - fn(x))/h
}
func x_squared(x: Double) -> Double {
return x * x
}
// Ideal answer: derivative of x^2 is 2x, so at point 3 the answer is 6
let d1 = derivativeOf(fn: x_squared, atX: 3) // d1 = 6.000000087880153
// Ideal answer: derivative of sin is cos, so at point pi/2 the answer is 0
let d2 = derivativeOf(fn: sin, atX: .pi/2) // d2 = -4.9960036108132044e-08
如果您打算从用户那里获得功能,那将是比较困难的部分。您可以给他们一些模板供他们选择:
- 三阶多项式:
y = Ax^3 + Bx^2 + Cx + D
- 正弦函数:
y = A * sin(B*x + C)
- 余弦函数:
y = A * cos(B*x + C)
- n 次根:
y = x ^ (1/N)
等然后你可以让他们给你 A、B、C、D 或 N
让我们看看这对于三阶多项式是如何工作的:
// Take coefficients A, B, C, and D and return a function which
// computes f(x) = Ax^3 + Bx^2 + Cx + D
func makeThirdOrderPolynomial(A a: Double, B b: Double, C c: Double, D d: Double) -> ((Double) -> Double) {
return { x in ((a * x + b) * x + c) * x + d }
}
// Get the coefficients from the user
let a = 5.0
let b = 3.0
let c = 1.0
let d = 23.0
// Use the cofficents to make the function
let f4 = makeThirdOrderPolynomial(A: a, B: b, C: c, D: d)
// Compute the derivative of f(x) = 5x^3 + 3x^2 + x + 23 at x = 5
// Ideal answer: derivative is f'(x) = 15x^2 + 6x + 1, f'(5) = 406
let d4 = derivativeOf(fn: f4, atX: 5) // d4 = 406.0000094341376
这个函数接受一个函数作为参数,return它的导数函数。 h是小位移,阶是相对于微分的。它使用递归进行高阶微分,所以它可能不是很稳定。
func differentiate(f:(Double)->(Double),_ h:Double=1e-4,_ order:Int=1)->(Double)->(Double){
var k=order
func diff(x: Double)-> Double{
return (-f(x+2*h)+8*f(x+h)-8*f(x-h)+f(x-2*h))/12/h
}
if(k==0){
return f
}
if(k<0){
fatalError("Order must be non-negative")
}
k=k-1
if(k>=1){
return differentiate(diff,h*10,k)
}
else{
return diff
}
}
print(differentiate({(x:Double)->(Double) in sin(x)},0.0001,4)(0))
我同意 Collin 的观点,这是一个很大的话题,可能没有完美的解决方案。然而,对于那些对有效但不完美的解决方案感到满意的人来说,vacawama 的答案非常简单。如果您想使用更多数学语法的导数函数,您可以定义一个运算符,幸运的是 Swift 使这变得异常容易。这是我所做的:
我首先为 return 导数的函数版本定义了一个运算符。我个人喜欢派生的 ➚ 字符,但是现有的 unicode 字符中有很大一部分是有效的 Swift 标识符。
postfix operator ➚ {}
postfix func ➚(f: Double -> Double) -> (Double -> Double) {
let h = 0.00000000001
func de(input: Double) -> Double {
return (f(input + h) - f(input)) / h
}
return de
}
接下来,让我们定义一个我们想要微分的函数:
func f(x: Double) -> Double {
return x*x + 2*x + 3
}
这可以这样使用:f➚
,这将 return a 作为 f 的导数的匿名函数。如果你想得到特定点的 f(例如让 x = 2),你可以这样调用它:(f➚)(2)
我决定我喜欢运算符,所以我做了另一个使语法看起来更好一点:
infix operator ➚ { associativity left precedence 140 }
func ➚(left: Double -> Double, right: Double) -> Double {
return (f➚)(right)
}
表达式 f➚2
现在 return 与 (f➚)(2)
相同,只是在做数学时使用起来更愉快。
问得好,每个人都回答得好,我只是想我要加点东西。如果您有任何问题,请告诉我!
数值方法可能最适合您,但如果您对解析方法感兴趣,它对于导数来说非常简单:
让我们来声明一个函数是什么(我们假设我们有一个参数的函数):
protocol Function {
func evaluate(value: Double) -> Double
func derivative() -> Function
}
现在让我们声明基本功能:
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())
}
}
一个函数的声明不是很好:
let xSquared = Power(operand1: Parameter(), operand2: Constant(constant: 2))
但我们可以evaluate
递归:
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
我想为我的应用程序的一部分创建一个函数,该函数 return 是函数在某个点的导数。显然,这是极限的正式定义。
但是什么样的函数能够return函数在swift中的一点的导数呢? swift 中的自动微分有什么想法吗?
不要试图重新发明轮子。数值微分(通常是数值分析)是一个很大的话题(有许多可能的解决方案 * 没有完美的解决方案),比你我都聪明得多的人已经提出了解决方案。除非您真的对所有不同的数值微分算法(它们的权衡、实现和优化)感兴趣,否则我建议您走另一条路。你说你用的是Swift?为什么不切换到 Objective-C(我假设您正在编写 iOS 或 OSX 应用程序)。如果这样做,您可以调出 GNU Scientific Library(这是一个 C、C++ 库)。也许你可以直接从 Swift 调用 c/c++ 代码?肯定是 IDK。
如果你真的想要,你可以看看他们的代码,看看他们是如何实现数值微分的解决方案的(不过,除非你准备好解决一些繁重的数学问题,否则我不会这样做)。
implementing the derivative in C/C++ * 你可以尝试使用它(我怀疑它是否非常可靠)。如果您需要精度和速度,我怀疑您是否也想在 Swift 中执行此操作。
这是一个基于上面公式的简单数值方法。您可以对此进行改进:
derivativeOf
采用函数 fn
和 x 坐标 x
和 returns fn
在 [=14= 处的导数的数值逼近]:
func derivativeOf(fn: (Double)->Double, atX x: Double) -> Double {
let h = 0.0000001
return (fn(x + h) - fn(x))/h
}
func x_squared(x: Double) -> Double {
return x * x
}
// Ideal answer: derivative of x^2 is 2x, so at point 3 the answer is 6
let d1 = derivativeOf(fn: x_squared, atX: 3) // d1 = 6.000000087880153
// Ideal answer: derivative of sin is cos, so at point pi/2 the answer is 0
let d2 = derivativeOf(fn: sin, atX: .pi/2) // d2 = -4.9960036108132044e-08
如果您打算从用户那里获得功能,那将是比较困难的部分。您可以给他们一些模板供他们选择:
- 三阶多项式:
y = Ax^3 + Bx^2 + Cx + D
- 正弦函数:
y = A * sin(B*x + C)
- 余弦函数:
y = A * cos(B*x + C)
- n 次根:
y = x ^ (1/N)
等然后你可以让他们给你 A、B、C、D 或 N
让我们看看这对于三阶多项式是如何工作的:
// Take coefficients A, B, C, and D and return a function which
// computes f(x) = Ax^3 + Bx^2 + Cx + D
func makeThirdOrderPolynomial(A a: Double, B b: Double, C c: Double, D d: Double) -> ((Double) -> Double) {
return { x in ((a * x + b) * x + c) * x + d }
}
// Get the coefficients from the user
let a = 5.0
let b = 3.0
let c = 1.0
let d = 23.0
// Use the cofficents to make the function
let f4 = makeThirdOrderPolynomial(A: a, B: b, C: c, D: d)
// Compute the derivative of f(x) = 5x^3 + 3x^2 + x + 23 at x = 5
// Ideal answer: derivative is f'(x) = 15x^2 + 6x + 1, f'(5) = 406
let d4 = derivativeOf(fn: f4, atX: 5) // d4 = 406.0000094341376
这个函数接受一个函数作为参数,return它的导数函数。 h是小位移,阶是相对于微分的。它使用递归进行高阶微分,所以它可能不是很稳定。
func differentiate(f:(Double)->(Double),_ h:Double=1e-4,_ order:Int=1)->(Double)->(Double){
var k=order
func diff(x: Double)-> Double{
return (-f(x+2*h)+8*f(x+h)-8*f(x-h)+f(x-2*h))/12/h
}
if(k==0){
return f
}
if(k<0){
fatalError("Order must be non-negative")
}
k=k-1
if(k>=1){
return differentiate(diff,h*10,k)
}
else{
return diff
}
}
print(differentiate({(x:Double)->(Double) in sin(x)},0.0001,4)(0))
我同意 Collin 的观点,这是一个很大的话题,可能没有完美的解决方案。然而,对于那些对有效但不完美的解决方案感到满意的人来说,vacawama 的答案非常简单。如果您想使用更多数学语法的导数函数,您可以定义一个运算符,幸运的是 Swift 使这变得异常容易。这是我所做的:
我首先为 return 导数的函数版本定义了一个运算符。我个人喜欢派生的 ➚ 字符,但是现有的 unicode 字符中有很大一部分是有效的 Swift 标识符。
postfix operator ➚ {}
postfix func ➚(f: Double -> Double) -> (Double -> Double) {
let h = 0.00000000001
func de(input: Double) -> Double {
return (f(input + h) - f(input)) / h
}
return de
}
接下来,让我们定义一个我们想要微分的函数:
func f(x: Double) -> Double {
return x*x + 2*x + 3
}
这可以这样使用:f➚
,这将 return a 作为 f 的导数的匿名函数。如果你想得到特定点的 f(例如让 x = 2),你可以这样调用它:(f➚)(2)
我决定我喜欢运算符,所以我做了另一个使语法看起来更好一点:
infix operator ➚ { associativity left precedence 140 }
func ➚(left: Double -> Double, right: Double) -> Double {
return (f➚)(right)
}
表达式 f➚2
现在 return 与 (f➚)(2)
相同,只是在做数学时使用起来更愉快。
问得好,每个人都回答得好,我只是想我要加点东西。如果您有任何问题,请告诉我!
数值方法可能最适合您,但如果您对解析方法感兴趣,它对于导数来说非常简单:
让我们来声明一个函数是什么(我们假设我们有一个参数的函数):
protocol Function {
func evaluate(value: Double) -> Double
func derivative() -> Function
}
现在让我们声明基本功能:
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())
}
}
一个函数的声明不是很好:
let xSquared = Power(operand1: Parameter(), operand2: Constant(constant: 2))
但我们可以evaluate
递归:
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