def find_zeroes(f, a, b, epsilon=1e-10):
    """
    Find the zero-crossing of the function f in the interval [a, b].  The function assumes that there is a single
    zero-crossing in the interval.

    :param f: The function.
    :param a: The lower bound of the interval.
    :param b: The upper bound of the interval.
    :param epsilon: The stopping tolerance.  When the interval is less that this, the function will return.  Defaults
                    to 1e-10.
    :return: The zero-crossing of f or None if there is no zero-crossing in the interval.
    """

    # Guard against someone getting the ordering of a and b wrong.
    low = min(a, b)
    high = max(a, b)
    middle = (low + high) / 2

    # Evaluate the functions, and store the results.  We're doing this to reduce the number of function evaluations
    # that we need, in case the function is expensive to evaluate.
    f_low = f(low)
    f_high = f(high)
    f_middle = f(middle)

    # If there's no zero-crossing in the interval, then we're done.  We can test this by looking at the sign of the
    # function evaluations at the bounds.  If they're different, then there's a zero-crossing.  An easy way to check
    # this is to multiply them together.  If they signs are different, then their product is negative.  If there's no
    # zero-crossing, return None.
    if f_low * f_high > 0:
        return None

    # If the interval is narrow enough, return the mid-point of it.  This is the base case of the recursion.
    if abs(high - low) < epsilon:
        return middle

    # If we haven't hit the base case, then we have to recursively call the function.  Pick the half of the interval
    # that contains the zero crossing, and call the function on that.  We can do this by looking at the sign of the
    # function evaluated at the mid-point.  If it's different from the function evaluated at the lower bound, then we
    # should keep the bottom half.
    if f_low * f_middle > 0:
        return find_zeroes(f, middle, high, epsilon)
    else:
        return find_zeroes(f, a, middle, epsilon)