Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
позволяет исключить риск данной (и любой подобной) ошибкиПросто спросите людей, которые пострадали от этой ошибки в реальных проектахНасколько я понял из поста, при всём количестве пользователей JDK, эта ошибка в JDK проявилась 1 раз за 9 лет.
В статье речь об алгоритмической чистоте, и если оставить код неизменным, а поменять лишь типы данных, то чистота кода никак не изменится и ошибка не исчезнет. Просто вероятность её возникновения станет меньше, но нулю равна не будет.Эээ, нет. Вы не правы.
IM: Computation of average could overflow (IM_AVERAGE_COMPUTATION_COULD_OVERFLOW)
The code computes the average of two integers using either division or signed right shift, and then uses the result as the index of an array. If the values being averaged are very large, this can overflow (resulting in the computation of a negative average). Assuming that the result is intended to be nonnegative, you can use an unsigned right shift instead. In other words, rather that using(low+high)/2, use(low+high) >>> 1
This bug exists in many earlier implementations of binary search and merge sort. Martin Buchholz found and fixed it in the JDK libraries, and Joshua Bloch widely publicized the bug pattern.
int newCapacity = capacity * 3 / 2;, вместо правильного int newCapacity = capacity + capacity / 2;.В С/C++ (где нет оператора >>>) можно написать так:
mid = ((unsigned int)low + (unsigned int)high)) >> 1;
int mid = (low + high) / 2;
>>, примененный к беззнаковому числу, заполняет старшие разряды нулями, как и >>> в Яве.public static int binarySearch(int[] a, int key) {
int low = 0;
int high = a.length - 1;
while (low <= high) {
int mid = (low + high) / 2;
int midVal = a[mid];
if (midVal < key)
low = mid + 1
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
int index3 = index1 + (index2 - index1 >> 1)На первый взгляд всё в порядке, но для достаточно больших low и high (а именно, если их сумма больше 231-1) возникает ошибка. Их сумма становится отрицательным числом, и mid также получается отрицательным.
Можно написать шаблон с беззнаковым целым T, и потом подставлять туда uint_8, uint_16 - их-то можно проверить по всему диапазону. Ну, и останется поверить в обобщенность шаблона для uint_32 и uint_64.
Почти во всех реализациях двоичного поиска и сортировки слиянием есть ошибка