Check which range a number is within

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-24 07:19:27

问题


I need to find which range a number, in this case value, is within. I cannot find any other way to set i to what I need other than this:

if value < -64:
  i = 0
elif value < -32:
  i = 1
elif value < -16:
  i = 2
elif value < -8:
  i = 3
elif value < -4:
  i = 4
elif value < -2:
  i = 5
elif value < -1:
  i = 6
elif value < -0.5:
  i = 7
elif value < 0:
  i = 8
elif value < 0.5:
  i = 9
elif value < 1:
  i = 10
elif value < 2:
  i = 11
elif value < 4:
  i = 12
elif value < 8:
  i = 13
elif value < 16:
  i = 14
elif value < 32:
  i = 15
elif value < 64:
  i = 16
else:
  i = 17

This is terrible code and I hate it. Is there any way I can do something like this?

ranges = [-64, -32, -16 ... 32, 64]
i = find_which_range(value, ranges)

Thanks!


回答1:


Use bisect:

import bisect

ranges = [-64, -32, -16, -8, -4, -2, -1, -0.5, 0, 0.5, 1, 2, 4, 8, 16, 32, 64]

print(bisect.bisect(ranges, -65))
# 0

print(bisect.bisect(ranges, -64))
# 1

print(bisect.bisect(ranges, 63))
#16

print(bisect.bisect(ranges, 64))
# 17

bisect.bisect(l, value) returns the index at which value would have to be inserted in l, such that all values to the left are less than value. It will also be fast to search a large list, as it uses a bisection algorithm.




回答2:


Based off the way you described you could do something like this:

ranges = [-64, -32, -16, -8, -4, -2, -1, -0.5, 0, 0.5, 1, 2, 4, 8, 16, 32, 64]

def build_ranges(power):
    ranges = [-0.5, 0, 0.5]
    for i in range(power):
        ranges.append(2**i)
        ranges.append(-2**i)
    return sorted(ranges)

def find_which_range(value, ranges):
    for i, range in enumerate(sorted(ranges)):
        if value < range:
            return i
    return None

output = find_which_range(value, ranges)



回答3:


Mathew provided a looping solution that works fine. But also observe that you are checking basically, which powers of 2 your number is between. Thus, you can take the log.

import math
a_value = abs(value)
sign = 1 if value > 0 else -1
lg_value = math.log2(a_value)
range_ = (2**(sign*math.floor(lg_value)), 2**(sign*math.ceil(lg_value)))

note that slight modifications are required for ranges < 1.




回答4:


People already provided much shorter (and efficient) solutions. I am just posting here my attempt just to show one more way and logic to approach the problem using list comprehension.

def find_which_range(value, ranges):
    if value <= min(ranges):
        c = 0
    elif value >= max(ranges): 
        c = len(ranges)
    else:
        c = [i+1 for i in range(len(ranges)-1) if ranges[i] <= value <= ranges[i+1]][0]
    return c

value = -9
i = find_which_range(value, ranges) 



回答5:


To find the right range, you can iterate over each range using zip function, like this:

ranges = [-64, -32, -16, -8, -4, -2, -1, -0.5, 0, 0.5, 1, 2, 4, 8, 16, 32, 64]

i = 9

for p, n in zip(ranges[:-1], ranges[1:]):
    if p <= i < n:
        r = p, n
        break
else:
    raise ValueError(i)

print(r)

You get: (8, 16)

Then you can use a mapping between each range and target values, something like this:

mapping = {
  (-64, -32): 1,
  (-32, -16): 2,
  (-16, -8): 3
}

print(mapping[(-32, -16)])
2


来源:https://stackoverflow.com/questions/51641395/check-which-range-a-number-is-within

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!