我正在尝试在min
和max
之间找到一个数字。我只知道(通过使用more
方法)我猜的数字是高于还是低于传递的数字。我需要找到的数字可以是小数,这让我感到紧张,因为平均二进制搜索似乎主要关注整数业务。
我编写的算法是尝试二进制搜索,没有数组。正如我所看到的,在经典二进制搜索之间的区别在于,搜索的值和索引已经被混合到同一个任务中。
var tolerance = 0;
var tries, min, max, current, needed;
function search () {
tries = 0;
min = 0;
max = 100;
needed = Math.random() * max;
current = (max - min) / 2;
while (!accept() && tries < 100) {
if (more(current))
min = current;
else
max = current;
current = min + ((max - min) / 2);
tries++;
}
results();
}
function more (n) {
return n < needed;
}
function accept () {
return Math.abs(current-needed) <= tolerance;
}
function results () {
document.getElementById('results').innerHTML = 'accepted: ' + current + '<br>needed: ' + needed + '<br>tries: ' + tries;
}
<button onclick="javascript:search();">search</button>
<br>
<div id="results"></div>
我的问题是这个;鉴于我想做什么,这段代码可以改进吗?或者也许有更好的方法一起完成这一切?显然,通过增加公差来大大提高尝试次数 - 但这会以最终结果的准确性为代价。例如,在经过一定次数的尝试后增加公差是否合理?
此外,如何最好地确保所需数量在范围内?我知道在尝试!more(max) && more(min)
循环之前我可以确保while
,但是有一种更简单的方法,而不是简单地在脚本的开头用螺栓连接两个额外的检查吗?
答案 0 :(得分:0)
搜索范围内的数字比搜索二进制搜索更难。
假设范围总是知道/类似,可以在search()函数之前使用more()函数或clamp函数进行验证。请参阅此链接clamp number
如果范围可以发生显着变化,可以使用某种指数函数来找到“良好范围”。
您还可以考虑将容差设置为百分比,或者设置为“好小数”。 See here
知道在搜索带有x小数的数字(即0到1000范围内的123.45)和0到100 000范围内搜索12345时,您将获得相同的效率。
由于“最坏情况”尝试次数为⌈log2(n + 1)⌉。有100次尝试允许您精确地找到0到n = 1267650600228229401496703205375范围内的数字。由于您有小数,对于您想要的每个小数精度,您需要将此数字除以10.
0.xxxxxx精度会给你一个0到12676506002282294014967032的范围,你可以在不到100次尝试中找到你的号码。
如果我的计算是正确的..
答案 1 :(得分:0)
当在实际间隔上进行二进制搜索时,不需要检查是否相等,而是继续优化搜索间隔,直到它足够小。
// 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
。
另请参阅:Binary searching on real numbers: Topcoder。
binary_search(lo, hi, p): while we choose not to terminate: mid = lo + (hi-lo)/2 if p(mid) == true: hi = mid else: lo = mid return lo // lo is close to the border between no and yes
由于实数集是密集的,应该很清楚我们通常无法找到确切的目标值。但是,我们可以快速找到一些x,使得f(x)在no和yes之间的边界的某个容差范围内。我们有两种方法来决定何时终止:当搜索空间小于某个预定界限(比如10 ^ -12)时终止,或者执行固定数量的迭代。