def binary_search(val, array):
    """
    >>> binary_search(1, [1, 2, 3])
    (0, 1)
    >>> binary_search(1.5, [1, 2, 3])
    (1, 2)
    >>> binary_search(8, [1, 2, 3])
    (None, None)
    >>> binary_search(3, [1, 2, 4])
    (2, 4)
    """

    # Trivial cases - out of array range.
    if len(array) == 0:
        return None, None

    if val > array[-1]:
        return None, None

    if val <= array[0]:
        return 0, array[0]

    low = 0
    high = len(array) - 1

    while high - low >= 2:
        mid = (high + low) // 2

        if array[mid] >= val:
            high = mid
        else:
            low = mid + 1

    if low == high:
        return low, array[low]

    if val > array[low]:
        return high, array[high]
    else:
        return low, array[low]