简体   繁体   中英

Python: fastest way to check in which interval number is in

Suppose I have split the interval [0, 1] into a series of smaller intervals [0, 0.2), [0.2, 0.4), [0.4, 0.9), [0.9, 1.0] . Now I sample a value r in [0, 1] . What is the fastest way I can check in which interval this belongs to using Python / Numpy / Pytorch?

The obvious way is this:

r = np.random.rand()
if 0 <= r < 0.2:
    pass # do something
elif 0.2 <= r < 0.4:
    pass # do something else
elif 0.4 <= r < 0.9:
    pass # do yet something else again
elif 0.9 <= r <= 1.0:
    pass # do some other thing


The bisect module contains a function bisect which uses a bisection algorithm to index into a sorted list. This should be roughly O(log n) .

from bisect import bisect

You can keep your rightmost values of your intervals in a list, and a list of functions which do something appropriate in the same order. Eg

def a():
    print("Do something")


intervals = [0.2, 0.4, 0.9, 1]

stufftodo = [a, a, a, a]

You can, of course, have different functions for each interval. You can then use the index returned by bisect to index into stufftodo , extract the appropriate function, and call it.

r = np.random.rand()
stufftodo[bisect(intervals, r)]()

You'll want to first transform your list of intervals into a list of boundaries, so instead of many intervals [0, 0.2), [0.2, 0.4), [0.4, 0.9), [0.9, 1.0] , you just define:

boundaries = [0, 0.2, 0.4, 0.9, 1.0]  # values must be sorted!!

Then you can perform a binary search over all of them, to see in which segment a value belongs:

index = bisect.bisect_right(boundaries, value)

index will be the index of the upper bound, so to get the range, you'd to:

range_low = boundaries[index - 1] if index > 0 else None
range_high = boundaries[index] if index < len(boundaries) else None

This will also take care of handling values which are not in any of the intervals. The binary search will be done in log(N) compares, which is the theoretical best thing you can do for arbitrary intervals.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM