I wrote a binary search to find the closest element to x in an array. How can show the correctness of the algorithm for any cases? Because it handles with floating points and variable length arrays, there are many cases.
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Random;
public class BinarySearchWithAFuzzinessTest {
/**
* Returns the first occurrence, that fulfills the constraints.
*/
public static int binaryContains(double[] list, double x, double delta) {
if (list == null || list.length == 0) {
throw new NoSuchElementException("provide at least one element");
}
int i = 0;
int j = list.length / 2;
int k = list.length - 1;
int r = -1;
if (x + delta < list[i]) {
return r;
}
if (Math.abs(x - list[i]) <= delta) {
r = i;
delta = Math.nextAfter(Math.abs(x - list[i]), -1);
}
if (Math.abs(x - list[j]) <= delta) {
r = j;
delta = Math.nextAfter(Math.abs(x - list[j]), -1);
}
if (Math.abs(x - list[k]) <= delta) {
r = k;
delta = Math.nextAfter(Math.abs(x - list[k]), -1);
}
while (true) {
System.out.println(i + " " + j + " " + k);
if (x < list[j]) {
k = j;
j = (i + j) / 2;
if (j == k) {
return r;
}
if (Math.abs(x - list[j]) <= delta) {
r = j;
delta = Math.nextAfter(Math.abs(x - list[j]), -1);
} else if (Math.abs(x - list[k]) <= delta) {
r = k;
delta = Math.nextAfter(Math.abs(x - list[k]), -1);
}
} else if (x < list[k]) {
i = j;
j = (j + k) / 2;
if (i == j) {
return r;
}
if (Math.abs(x - list[i]) <= delta) {
r = i;
delta = Math.nextAfter(Math.abs(x - list[i]), -1);
} else if (Math.abs(x - list[j]) <= delta) {
r = j;
delta = Math.nextAfter(Math.abs(x - list[j]), -1);
}
} else {
return r;
}
}
}
/**
* Returns the first occurrence, that fulfills the constraints. This is for testing.
*/
public static int linearContains(double[] list, double x, double delta) {
for (int i = 0; i < list.length; i++) {
if (Math.abs(x - list[i]) <= delta) {
delta = Math.abs(x - list[i]);
while (i + 1 < list.length && Math.abs(x - list[i + 1]) < delta) {
i++;
delta = Math.abs(x - list[i]);
}
return i;
}
}
return -1;
}
public static void main(String[] args) {
Random r = new Random(1234);
for (int i = 0; i < 100000; i++) {
double[] a = new double[1 + r.nextInt(20)];
double x = r.nextInt(20) - 10;
double delta = r.nextDouble();
for (int j = 0; j < a.length; j++) {
if (r.nextBoolean()) {
a[j] = x + r.nextDouble() * 5 * delta;
} else {
a[j] = x - r.nextDouble() * 5 * delta;
}
}
Arrays.sort(a);
int c1 = binaryContains(a, x, delta);
int c2 = linearContains(a, x, delta);
if (c1 != c2) {
System.out.println("OOPS " + x + " " + delta);
System.out.println(Arrays.toString(a) + " " + c1 + " " + c2);
break;
}
}
double[] a = {4, 4, 4};
System.out.println(binaryContains(a, 4, 0));
System.out.println(linearContains(a, 4, 0));
}
}