在JavaScript中实现带容差的二进制搜索?

在JavaScript中实现带容差的二进制搜索?,javascript,math,while-loop,binary-search,Javascript,Math,While Loop,Binary Search,我试图找到一个介于min和max之间的数字。我只知道(通过使用more方法)我猜测的数字是高于还是低于传递的数字。我需要找到的数字可以是十进制,这让我很紧张,因为平均二进制搜索似乎主要关注整数的业务 我写的算法是在不使用数组的情况下进行二进制搜索的尝试。在我看来,经典二进制搜索之间的区别在于,搜索的值和索引已合并到同一个任务中 var容差=0; var、最小值、最大值、当前值、所需值; 函数搜索(){ 尝试=0; 最小值=0; 最大值=100; 需要=Math.random()*最大值; 电流

我试图找到一个介于
min
max
之间的数字。我只知道(通过使用
more
方法)我猜测的数字是高于还是低于传递的数字。我需要找到的数字可以是十进制,这让我很紧张,因为平均二进制搜索似乎主要关注整数的业务

我写的算法是在不使用数组的情况下进行二进制搜索的尝试。在我看来,经典二进制搜索之间的区别在于,搜索的值和索引已合并到同一个任务中

var容差=0;
var、最小值、最大值、当前值、所需值;
函数搜索(){
尝试=0;
最小值=0;
最大值=100;
需要=Math.random()*最大值;
电流=(最大-最小)/2;
而(!accept()&&trys<100){
如果(更多(当前))
最小值=电流;
其他的
最大值=电流;
电流=最小值+((最大-最小)/2);
尝试++;
}
结果();
}
功能更多(n){
返回n<所需;
}
函数接受(){

return Math.abs(当前需要)在搜索范围内的数字时,很难比二进制搜索做得更好

假设范围始终为已知/相似,则可以使用more()函数或clamp函数在search()函数之前进行验证。请参阅此链接

如果范围可以急剧变化,可以使用某种指数函数来找到“好的范围”

  • 范围0-100
  • 范围101至1000
  • 范围从1001到20000
  • 等等
你也可以考虑将你的容忍度设置为一个百分比,或者设置为一个“好小数”

要知道,搜索带有x位小数的数字(即0到1000范围内的123.45)和搜索0到100000范围内的12345时,您将获得相同的效果

由于“最坏情况”的尝试次数为⌈log2(n+1)⌉. 尝试100次可以让您精确地找到0到n=1267650600228229401496703205375之间的数字。因为您有小数,所以对于所需精度的每一个小数,您需要将该数字除以10

0.xxxxxx精度将为您留下一个0到12676506002282294014967032的范围,在此范围内,您可以在不到100次的尝试中找到您的号码


如果我的计算正确..

很难比二进制搜索更好地搜索范围内的数字

假设范围始终为已知/相似,则可以使用more()函数或clamp函数在search()函数之前进行验证。请参阅此链接

如果范围可以急剧变化,可以使用某种指数函数来找到“好的范围”

  • 范围0-100
  • 范围101至1000
  • 范围从1001到20000
  • 等等
你也可以考虑将你的容忍度设置为一个百分比,或者设置为一个“好小数”

要知道,搜索带有x位小数的数字(即0到1000范围内的123.45)和搜索0到100000范围内的12345时,您将获得相同的效果

由于“最坏情况”的尝试次数为⌈log2(n+1)⌉. 尝试100次可以让您精确地找到0到n=1267650600228229401496703205375之间的数字。因为您有小数,所以对于所需精度的每一个小数,您需要将该数字除以10

0.xxxxxx精度将为您留下一个0到12676506002282294014967032的范围,在此范围内,您可以在不到100次的尝试中找到您的号码


如果我的计算是正确的..

当在实区间上进行二进制搜索时,不需要检查是否相等,而是继续细化搜索区间,直到它足够小

// Generated by CoffeeScript 1.10.0
(function() {
  var eps, hi, lo, mid, more, secret;

  // This is your tolerance value.
  eps = 0.01;

  // The binary search routine will never get to see this.
  secret = 45.63;

  more = function(test) {
    return test > secret;
  };

  lo = 0;

  hi = 100;

  while (hi - lo > eps) {
    mid = lo + ((hi - lo) / 2);
    if (more(mid)) {
      hi = mid;
    } else {
      lo = mid;
    }
  }

  console.log(mid);

}).call(this);
输出:
45.635986328125


当值超出范围时,输出将等于
lo
hi
,其中等于意味着它们的绝对差值将小于
eps


另见:

由于实数集是稠密的,我们通常无法找到确切的目标值,这一点应该很清楚。然而,我们可以很快找到一些x,比如f(x)在“否”和“是”之间的边界范围内。我们有两种方法来决定何时终止:当搜索空间小于某个预定边界(例如10^-12)时终止,或者执行固定次数的迭代


当在实区间上进行二进制搜索时,不需要检查是否相等,而是不断细化搜索区间,直到它足够小为止

// Generated by CoffeeScript 1.10.0
(function() {
  var eps, hi, lo, mid, more, secret;

  // This is your tolerance value.
  eps = 0.01;

  // The binary search routine will never get to see this.
  secret = 45.63;

  more = function(test) {
    return test > secret;
  };

  lo = 0;

  hi = 100;

  while (hi - lo > eps) {
    mid = lo + ((hi - lo) / 2);
    if (more(mid)) {
      hi = mid;
    } else {
      lo = mid;
    }
  }

  console.log(mid);

}).call(this);
输出:
45.635986328125


当值超出范围时,输出将等于
lo
hi
,其中等于意味着它们的绝对差值将小于
eps


另见:

由于实数集是稠密的,我们通常无法找到确切的目标值,这一点应该很清楚。然而,我们可以很快找到一些x,比如f(x)在“否”和“是”之间的边界范围内。我们有两种方法来决定何时终止:当搜索空间小于某个预定边界(例如10^-12)时终止,或者执行固定次数的迭代


我会将accept函数更改为
Math.abs(当前需要)@Wikunia你是对的-这有点草率。可能是@Rishav的重复,但这不适用。我这里的主要问题是,这可以改进吗?或者有更好的方法实现同样的目标吗?就个人而言,我宁愿在执行搜索函数之前验证数字是否在范围内。你可以使用你的more()当然,如果您愿意,也可以使用钳制函数,例如(请参见链接),我会将accept函数更改为
Math.abs(当前需要)@Wikunia您是对的-这有点草率。可能是@Ris的重复