简体   繁体   English

找到函数的转折点

[英]Finding the turning point of a function

I'd like to the first value that outputs True for my function. 我想要为我的函数输出True的第一个值。 I currently have a search that works fine, but I think is still a bit inefficient. 我目前有一个搜索工作正常,但我认为仍然有点低效。 Could anyone suggest a better binary search? 有谁能建议更好的二元搜索? My code is below, simplified. 我的代码如下,简化。

guess = 2
limits = [2, 2**35] #The search area

while True:
    if myFunction(guess) == False:
        limits[0] = max(limits[0], guess) #Limit the search area
        guess *= 2
    else:
        limits[1] = min(limits[1], guess) #Limit the search area
        guess = int((limits[0] + limits[1])/2) #The guess is the midpoint of the search area
        if myFunction(guess) == True and myFunction(guess-1) == False:
            return guess

This is the classical problem of finding a level-crossing of a monotonically increasing or decreasing function. 这是找到单调增加或减少函数的平交的经典问题。 As you guessed, it is solvable by binary search . 正如您猜测的那样, 二元搜索可以解决这个问题。 Your code has some bugs, which is not surprising: 您的代码有一些错误,这并不奇怪:

Although the idea is simple, implementing binary search correctly requires attention to some subtleties about its exit conditions and midpoint calculation. 虽然这个想法很简单,但正确实现二进制搜索需要注意其退出条件和中点计算的一些细微之处。

So, you should avoid writing your own binary search when possible. 因此,您应尽可能避免编写自己的二进制搜索。 Fortunately, Python offers a library module bisect which can do the job for you. 幸运的是,Python提供了一个可以为您完成工作的库模块bisect

from bisect import bisect_left

MIN = 2
MAX = 2**35

def search(f):
   # Finds the first position of `True` in `f`
   return bisect_left(f, True, lo=MIN, hi=MAX + 1)

Don't be confused by the fact that bisect only works with indexable objects: there is no need to create a list with 2**35 elements. 不要因为bisect只适用于可索引对象这一事实而感到困惑:不需要创建一个包含2**35元素的列表。 You can use a generator object instead using the __getitem__ syntax. 您可以使用__getitem__语法来使用生成器对象。 To do that, encapsulate your function in a class and define the getter method that would return False for all argument values on the left side of the point of interest and True otherwise. 为此,将函数封装在一个类中,并定义getter方法,该方法将为感兴趣点左侧的所有参数值返回False ,否则为True

def myFunction1(index):
   return index >= 1456
def myFunction2(index):
   return index >= 2
def myFunction3(index):
   return index >= MAX - 1

class F:
   def __init__(self, f):
      self.f = f
   def __getitem__(self, index):
      return self.f(index)

# testing code
print(search(F(myFunction1))) # prints 1456
print(search(F(myFunction2))) # prints 2
print(search(F(myFunction3))) # prints MAX - 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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