二进制搜索以找到最接近目标数字的浮点值
binary Search to find closest float value to target number
我有一些问题,也许你们中的一个可以帮助我,
我有一个浮点数组,但找不到最接近目标数字的浮点值(float)
我使用 javascript 进行简单的二进制搜索,然后我就卡住了。
function binarySearch(arr, val, start = 0, end = arr.length - 1) {
const mid = Math.floor((start + end) / 2);
if(Math.abs(val - arr[mid]) < Math.abs(val - arr[mid + 1])){
return mid;
}
if (start >= end) {
return -1;
}
return val < arr[mid]
? binarySearch(arr, val, start, mid - 1)
: binarySearch(arr, val, mid + 1, end);
}
let array = [0,0.03336667683886884,0.06673335367773768,0.10010003051660653,0.13346670735547536,0.1668333841943442,0.20020006103321306]
let result = binarySearch(array,'0.166833') //=> This value needs to be returned 0.1668333841943442
你的停止条件被打破。在您的示例中,如果您输入以下数组:
[0.3, 0.5, 0.8, 2.0]
你在开始时有:
arr[mid] = 0.5
arr[mid + 1] = 0.8
因此,如果您将 val = 0.1
提供给您的算法,您将拥有:
Math.abs(val - arr[mid]) = 0.4
Math.abs(val - arr[mid + 1]) = 0.7
因此,尽管您期望 0.3
的索引,但您将 return 0.5
的索引。
解决您的问题的伪想法是:
if array contains 1 element => return element
else if array contains 2 elements => return element closest to val.
else if val < array[mid] => recurse on first half
else if val > array[mid] => recurse on second half
你的条件 Math.abs(val - arr[mid]) < Math.abs(val - arr[mid + 1])
是错误的,你总是检查左边的值比右边的值更接近,所以即使对于数组 [10, 20, 30, 40] 中的值 1,当你检查数字20、1 比 30 更接近 20 - 然后返回不正确的结果。
此外,您需要检查边缘情况,索引 mid + 1
可能不可用。并且该值可能小于最小值或大于最大值,因此可能会出现无限循环。
让我为您提供这个解决方案:
function binarySearch(arr, val, start, end) {
// edge case: value of smaller than min or larger than max
if(array[0] >= val) return 0;
if(array[array.length - 1] <= val) return array.length - 1;
while (start <= end) {
let mid = Math.floor((end + start) / 2);
// value is in interval from previous to current element
if(val >= arr[mid - 1] && val <= arr[mid]) {
return Math.abs(val - arr[mid - 1]) < Math.abs(val - arr[mid]) ? mid - 1 : mid;
}
else {
if(arr[mid] < val) {
start = mid + 1;
}
else {
end = mid - 1;
}
}
}
return -1;
}
看来你打错了。您不应该 return mid
索引,而是 array[mid]
:
中的数组项
function binarySearch(arr, val, start = 0, end = arr.length - 1) {
const mid = Math.floor((start + end) / 2);
if(Math.abs(val - arr[mid]) < Math.abs(val - arr[mid + 1])){
return arr[mid];
}
if (start >= end) {
return -1;
}
return val < arr[mid]
? binarySearch(arr, val, start, mid - 1)
: binarySearch(arr, val, mid + 1, end);
}
let array = [0, 0.03336667683886884, 0.06673335367773768, 0.10010003051660653,
0.13346670735547536, 0.1668333841943442, 0.20020006103321306];
console.log(binarySearch(array,'0.166833')) // 0.1668333841943442
我找到了这个解决方案,但我需要 return 正确值的索引
function binarySearch(arr, target, lo = 0, hi = arr.length - 1) {
if (target < arr[lo]) {return arr[0]}
if (target > arr[hi]) {return arr[hi]}
const mid = Math.floor((hi + lo) / 2);
return hi - lo < 2
? (target - arr[lo]) < (arr[hi] - target) ? arr[lo] : arr[hi]
: target < arr[mid]
? binarySearch(arr, target, lo, mid)
: target > arr[mid]
? binarySearch(arr, target, mid, hi)
: arr[mid]
}
let array = [0, 0.03336667683886884, 0.06673335367773768, 0.10010003051660653,0.13346670735547536, 0.1668333841943442, 0.20020006103321306,30.01];
console.log(binarySearch(array,0.03336))
我有一些问题,也许你们中的一个可以帮助我, 我有一个浮点数组,但找不到最接近目标数字的浮点值(float)
我使用 javascript 进行简单的二进制搜索,然后我就卡住了。
function binarySearch(arr, val, start = 0, end = arr.length - 1) {
const mid = Math.floor((start + end) / 2);
if(Math.abs(val - arr[mid]) < Math.abs(val - arr[mid + 1])){
return mid;
}
if (start >= end) {
return -1;
}
return val < arr[mid]
? binarySearch(arr, val, start, mid - 1)
: binarySearch(arr, val, mid + 1, end);
}
let array = [0,0.03336667683886884,0.06673335367773768,0.10010003051660653,0.13346670735547536,0.1668333841943442,0.20020006103321306]
let result = binarySearch(array,'0.166833') //=> This value needs to be returned 0.1668333841943442
你的停止条件被打破。在您的示例中,如果您输入以下数组:
[0.3, 0.5, 0.8, 2.0]
你在开始时有:
arr[mid] = 0.5
arr[mid + 1] = 0.8
因此,如果您将 val = 0.1
提供给您的算法,您将拥有:
Math.abs(val - arr[mid]) = 0.4
Math.abs(val - arr[mid + 1]) = 0.7
因此,尽管您期望 0.3
的索引,但您将 return 0.5
的索引。
解决您的问题的伪想法是:
if array contains 1 element => return element
else if array contains 2 elements => return element closest to val.
else if val < array[mid] => recurse on first half
else if val > array[mid] => recurse on second half
你的条件 Math.abs(val - arr[mid]) < Math.abs(val - arr[mid + 1])
是错误的,你总是检查左边的值比右边的值更接近,所以即使对于数组 [10, 20, 30, 40] 中的值 1,当你检查数字20、1 比 30 更接近 20 - 然后返回不正确的结果。
此外,您需要检查边缘情况,索引 mid + 1
可能不可用。并且该值可能小于最小值或大于最大值,因此可能会出现无限循环。
让我为您提供这个解决方案:
function binarySearch(arr, val, start, end) {
// edge case: value of smaller than min or larger than max
if(array[0] >= val) return 0;
if(array[array.length - 1] <= val) return array.length - 1;
while (start <= end) {
let mid = Math.floor((end + start) / 2);
// value is in interval from previous to current element
if(val >= arr[mid - 1] && val <= arr[mid]) {
return Math.abs(val - arr[mid - 1]) < Math.abs(val - arr[mid]) ? mid - 1 : mid;
}
else {
if(arr[mid] < val) {
start = mid + 1;
}
else {
end = mid - 1;
}
}
}
return -1;
}
看来你打错了。您不应该 return mid
索引,而是 array[mid]
:
function binarySearch(arr, val, start = 0, end = arr.length - 1) {
const mid = Math.floor((start + end) / 2);
if(Math.abs(val - arr[mid]) < Math.abs(val - arr[mid + 1])){
return arr[mid];
}
if (start >= end) {
return -1;
}
return val < arr[mid]
? binarySearch(arr, val, start, mid - 1)
: binarySearch(arr, val, mid + 1, end);
}
let array = [0, 0.03336667683886884, 0.06673335367773768, 0.10010003051660653,
0.13346670735547536, 0.1668333841943442, 0.20020006103321306];
console.log(binarySearch(array,'0.166833')) // 0.1668333841943442
我找到了这个解决方案,但我需要 return 正确值的索引
function binarySearch(arr, target, lo = 0, hi = arr.length - 1) {
if (target < arr[lo]) {return arr[0]}
if (target > arr[hi]) {return arr[hi]}
const mid = Math.floor((hi + lo) / 2);
return hi - lo < 2
? (target - arr[lo]) < (arr[hi] - target) ? arr[lo] : arr[hi]
: target < arr[mid]
? binarySearch(arr, target, lo, mid)
: target > arr[mid]
? binarySearch(arr, target, mid, hi)
: arr[mid]
}
let array = [0, 0.03336667683886884, 0.06673335367773768, 0.10010003051660653,0.13346670735547536, 0.1668333841943442, 0.20020006103321306,30.01];
console.log(binarySearch(array,0.03336))