2015-07-12 70 views
0

参数如果我有这样一个功能:查找函数给出的函数结果迅速

func evaluateGraph(sender: GraphView, atX: Double) -> Double? { 
     return function?(atX) 
    } 

function是一个变量早些时候宣布,它是一个数学表达式(如x^2)。本质上,该函数返回给定其x值的数学表达式的y值。给出结果,我怎么能找到这个function的参数atX。如果y值为零,那么x值必须是0,0的结果吗?

+2

这实在是一个数学问题,而不是一个快速的问题。 – sbooth

+0

@sbooth这是关于返回给定结果的函数的参数。 – modesitt

+0

@DylanModesitt是的。这是一个数学问题。没有办法以编程方式反转方法... – nhgrif

回答

1

假设你只是想知道反函数在GraphView(这是希望不是无限的),你可以使用这样的:在大约0.5秒

// higher percision -> better accuracy, start...end: Interval, f: function 
func getZero(#precision: Int, var #start: Double, var #end: Double, f: Double -> Double) -> Double? { 

    let fS = f(start) 
    let fE = f(end)  

    let isStartNegative = fS.isSignMinus 
    if isStartNegative == fE.isSignMinus { return nil } 

    let fMin = min(fS, fE) 
    let fMax = max(fS, fE) 

    let doublePrecision = pow(10, -Double(precision)) 

    while end - start > doublePrecision { 
     let mid = (start + end)/2 
     let fMid = f(mid) 
     if fMid < fMin || fMax < fMid { 
      return nil 
     } 
     if (fMid > 0) == isStartNegative { 
      end = mid 
     } else { 
      start = mid 
     } 
    } 

    return (start + end)/2 
} 

// same as above but it returns an array of points 
func getZerosInRange(#precision: Int, #start: Double, #end: Double, f: Double -> Double) -> [Double] { 

    let doublePrecision = pow(10, -Double(precision)) 

    /// accuracy/step count between interval; "antiproportional" performance!!!! 
    let stepCount = 100.0 
    let by = (end - start)/stepCount 
    var zeros = [Double]() 

    for x in stride(from: start, to: end, by: by) { 
     if let xZero = getZero(precision: precision, start: x, end: x + by, f) { 
      zeros.append(xZero) 
     } 
    } 
    return zeros 
} 

// using currying; all return values should be elements of the interval start...end 
func inverse(#precision: Int, #start: Double, #end: Double, f: Double -> Double)(_ x: Double) -> [Double] { 
    return getZerosInRange(precision: precision, start: start, end: end) { f($0) - x } 
} 

let f = { (x: Double) in x * x } 

// you would pass the min and max Y values of the GraphView 
// type: Double -> [Double] 
let inverseF = inverse(precision: 10, start: -10, end: 10, f) 

inverseF(4) // outputs [-1.999999999953436, 2.000000000046564] 

有趣的是这个代码RUND在操场我没有想到。

+0

这是相当辉煌的。我使用牛顿方法来查找零,但已将我的应用程序切换到此逻辑。谢谢。 – modesitt

+0

我以前也使用过牛顿法,但是我发现使用'getZero'查找零点更慢。此外,这也导致许多类似的零点必须被整理/合并。但是你应该考虑当前版本中的一个问题,它不能像x^2那样找到没有转换的零点。然后你可以使用牛顿法来找到确切的一个。如果工作正常,我会编辑我的答案。 – Qbyte

+0

我对1/x等极点的函数进行了改进,它将在x = 0时计算一个零点。此外,if语句现在更短。 (见编辑答案) – Qbyte

1

你可以创建一个反函数来做相反的事情。

所以f(x) = y inverse f'给出f'(y) = x

因此,如果您定义的函数是平方输入,那么反函数将返回平方根等等。

你可能会遇到麻烦,喜欢的东西,虽然作为f'(1) = 1 and -1在其中,f(x)返回广场上的情况。

1

短的实际编写的逆方法,以实际负推断出输入给予了提供的输出,我们所能做的最好的就是写我们的程序作出的猜测,直到它在一定精度范围内的唯一途径。

因此,举例来说,假设我们有square功能:

func square(input: Double) -> Double { 
    return input * input 
} 

现在,如果我们不希望纠正这一函数的反函数(实际上有两个输入对于任何给定输出) ,那么我们必须编写一个猜测函数。在答案

func inverseFunction(output: Double, function: (Double)->Double) -> Double 

这需要表示输出一个double,和一个函数(即所产生的输出的一个),并返回它的最佳猜测。

那么,我们如何猜测?

好了,我们在微积分和积分的任何1类的早期部分做同样的方式。选择一个起始数字,通过函数运行,将结果与我们要查找的输出进行比较。记录三角洲。选择第二个数字,通过函数运行,将结果与我们要查找的输出进行比较。记录增量,将其与第一个增量进行比较。

不断为此直到已减至最小增量到一个可接受的精度水平(0.1增量好吗?0.01?0.0001?)。增量越小,计算时间越长。但无论如何,这将需要很长时间。

至于猜测算法?这是一个我无法回答的数学问题。我甚至不知道从哪开始。

最后,你最好的选择是简单地写反函数为你想要逆任何功能。