衍生函数在swift?

时间:2015-06-23 23:01:49

标签: ios swift calculus

我想创建一个函数,在我的应用程序的某个部分返回函数的派生。我不知道怎么会这样做。显然,这是限制的正式定义。

enter image description here

但是什么样的函数能够在某一点上返回函数的导数?我真的不在乎用户输入什么,因为我可以在某一点计算导数。有什么想法吗?

5 个答案:

答案 0 :(得分:10)

以下是基于上述公式的简单数值方法。你可以改进这个:

derivativeOf接受函数fn和x坐标x,并返回fn x的导数的数值近似值:

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

如果您打算从用户那里获取功能,那就更难了。您可以为他们提供一些模板供您选择:

  1. 三阶多项式:y = Ax^3 + Bx^2 + Cx + D
  2. sin函数:y = A * sin(B*x + C)
  3. cos函数:y = A * cos(B*x + C)
  4. nth root:y = x ^ (1/N)
  5. 等。然后你可以让他们给你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
    

答案 1 :(得分:6)

数值方法对您来说可能是最好的,但如果您对分析方法感兴趣,那么对于衍生工具来说非常简单:

让我们声明一个函数是什么(我们假设我们有一个参数的函数):

idsAndPrices.Where(...)

现在让我们宣布基本功能:

join

函数的声明不是很好:

var dbQuery = 
    from r in myReadings
    where lookupProducts.Contains(r.ProductId)
    select new { ProductId = r.ProductId, Price = r.Price };
var query =
    from p in lookupProducts
    join r in dbQuery on p equals r.ProductId into rGroup
    from r in rGroup.DefaultIfEmpty().Take(1)
    select r?.Price;
var result = query.ToArray();

但我们可以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())
    }
}

答案 2 :(得分:4)

我同意Collin的看法,这是一个很大的话题,而且可能没有完美的解决方案。然而,对于那些有效但不完美的解决方案,vacawama的答案非常简单。如果你想使用衍生函数和更多的数学语法,你可以定义一个运算符,幸运的是,Swift非常容易。这是我做的:

我首先定义了一个运算符,只返回导数的函数版本。我个人喜欢衍生词的➚字符,但现有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➚,它将返回一个匿名函数,它将是f的导数。如果您希望获得特定点的f(例如,让x = 2),您可以这样调用它:(f➚)(2)

我决定我喜欢运算符,所以我又做了另一个让语法看起来更好一点:

infix operator ➚ { associativity left precedence 140 }
func ➚(left: Double -> Double, right: Double) -> Double {
    return (f➚)(right)
}

表达式f➚2现在将返回与(f➚)(2)相同的东西,在您进行数学运算时使用它会更加愉快。

好问题,每个人都很好的答案,我只是觉得我会额外加上一些东西。如果您有任何问题,请告诉我们!

答案 3 :(得分:2)

不要试图重新发明轮子。数值分析(数值分析,一般而言)是一个巨大的主题(有许多可能的解决方案*没有完美的解决方案)和人们比你和我已经提出解决方案更聪明。除非你真的对所有不同的数值微分算法(他们的权衡,实现和优化)感兴趣,否则我建议你去另一条路线。你说你正在使用Swift吗?为什么不切换到Objective-C(我假设您正在编写iOS或OSX应用程序)。如果你这样做,你可以调用GNU Scientific Library(这是一个C,C ++库)。也许你可以直接从Swift调用c / c ++代码? IDK肯定。

如果你真的想要,你可以查看他们的代码,看看他们是如何实现他们的数字差异化解决方案的(但是,除非你准备好解决一些重的问题,否则我不会这样做数学)。

implementing the derivative in C/C++ *你可以尝试使用它(我怀疑这是非常强大的)。如果你需要精确度和速度,我怀疑你是否想要这样做也是在Swift中。

答案 4 :(得分:2)

此函数将函数作为参数并返回其派生函数。 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))