def average(x, y):
    return (x + y) / 2
def positive(x):
    return x > 0
def negative(x):
    return x < 0
def abs(x):
    return x if x >= 0 else - x
def close_enough(x, y):
    return abs(x - y) < 0.001
def search(f, neg_point, pos_point):
    midpoint = average(neg_point, pos_point)
    if close_enough(neg_point, pos_point):
        return midpoint
    else:
        test_value = f(midpoint)
        if positive(test_value):
            return search(f, neg_point, midpoint)
        elif negative(test_value):
            return search(f, midpoint, pos_point)
        else: return midpoint
def half_interval_method(f, a, b):
    a_value = f(a)
    b_value = f(b)
    if negative(a_value) and positive(b_value):
        return search(f, a, b) 
    elif negative(b_value) and positive(a_value):
        return search(f, b, a)
    else: error("values are not of opposite sign")
print(half_interval_method(lambda x: x * x * x - 2 * x - 3, 1, 2))

# expected: 1.89306640625
