Emre Değirmenci
Emre Değirmenci

Reputation: 747

Splitting method algorithm

(x^3 - 2x^2 - 5) is my equation.First of all I have two values like x = 2 and x = 4. My first two values must be count for equation and them results must be negative and positive each time. And second step is (2 + 4) / 2 = 3 this time x = 3 in equation. And the math operation continue with last one positive value and one negative value. I try this

var x = 2.0
var equation = pow(x, 3) - 2 * pow(x, 2) - 5

switch x {
case x : 2
equation = pow(x, 3) - 2 * pow(x, 2) - 5
case x : 4
equation = pow(x, 3) - 2 * pow(x, 2) - 5
default:
0
}  
print(equation)

How can I assign first two values like 2 and 4 for one var x ?

Upvotes: 2

Views: 124

Answers (1)

Martin R
Martin R

Reputation: 539975

Apparently you want to implement the bisection method to find the (real) solution (“root”) of an equation. The first step is to define that equation as a function, so that it can be evaluated at various points:

func f(_ x: Double) -> Double {
    return pow(x, 3) - 2 * pow(x, 2) - 5
}

Then you need two variables for the left and right boundary of the current interval. These must be chosen such that f(x) has opposite signs at the boundaries. In your example:

var xleft = 2.0   // f(xleft) < 0
var xright = 4.0  // f(xright) > 0

Now you can start the iteration: Compute f(x) at the midpoint of the current interval, and replace xleft of xright, depending on whether f(x) is negative or positive. Continue until the approximation is good enough for your purposes:

let eps = 0.0000001 // Desired precision
let leftSign = f(xleft).sign

repeat {
    let x = (xleft + xright)/2.0
    let y = f(x)
    if y == 0 {
        xleft = x
        break
    } else if y.sign == leftSign {
        xleft = x
    } else {
        xright = x
    }
    // print(xleft, xright)
} while xright - xleft > eps

// Print approximate solution:
print(xleft)

The next step would be to implement the bisection method itself as a function:

func bisect(_ f: ((Double) -> Double), xleft: Double, xright: Double, eps: Double = 1.0e-6) -> Double {
    let yleft = f(xleft)
    let yright = f(xright)

    precondition(yleft * yright <= 0, "f must have opposite sign at the boundaries")

    var xleft = xleft
    var xright = xright

    repeat {
        let x = (xleft + xright)/2.0
        let y = f(x)
        if y == 0 {
            return x
        } else if y.sign == yleft.sign {
            xleft = x
        } else {
            xright = x
        }
    } while xright - xleft > eps

    return (xleft + xright)/2.0
}

so that it can be used with arbitrary equations:

let sol1 = bisect({ x in pow(x, 3) - 2 * pow(x, 2) - 5 }, xleft: 2.0, xright: 4.0)
print(sol1) // 2.690647602081299

let sol2 = bisect({ x in cos(x/2)}, xleft: 3.0, xright: 4.0, eps: 1.0e-15)
print(sol2) // 3.1415926535897936

Upvotes: 3

Related Questions