2016-04-05 3 views
3

Я пытаюсь понять двоичный поиск ошибка с byte массив, я понял понятие переполнения, которое происходит при вычислении индекса mid. Однако, когда я моделировать такое же поведение с помощью byte массива следующим образом:Понимание двоичного поиска ошибка

public byte binarySearch(byte[] arr, byte low, byte high, byte value){ 

     if(low>high){ 
      return -1; 
     } 

     /* Line 1 */ byte overflow_mid = (byte) (((byte) (low + high))/2); // This line giving overflow behaviour 

     /* Line 2 */ byte mid = (byte) ((low + high)/2);  // however this line doesn't, which is not what i expected 

     if(arr[mid]== value){ 
      return mid; 
     } 

     if(arr[mid]>value){ 
      return binarySearch(arr, low, (byte) (mid-1), value); 
     } 
     return binarySearch(arr, mid, high, value); 
    } 

Интуиция:

Поскольку низкие и высокие переменные типа byte, я считаю, что не нужно явное приведение byte снова при расчете индекса в серединев строке 2.

Благодарности

+0

Зачем использовать 'byte' для' low' и 'high'? Они являются значениями индекса, а не значениями массива, поэтому просто используйте 'int', и у вас не должно быть проблем с переполнением, и это устранит необходимость всех этих бросков dang. Значения индекса массива повышаются до 'int' в любом случае (см. [JLS 15.13. Выражения доступа к массиву] (https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.13)), поэтому вы ничего не спасаете. – Andreas

+0

Да, вы абсолютно правы, но я пытаюсь понять ошибку, моделируя целочисленное поведение с помощью байтового индекса и байтового массива, поэтому я ожидаю, что он сработает. Просто из любопытства. –

ответ

2

Скажет, что byte low = 50, high = 100.

Выражение low + high будет сначала рекламировать как int, затем добавить их, в результате чего значение 150 (int).

В версии 1 вы затем набрасываете 150 (int) на byte, что является значением -106 (byte). Переполнение. То же, что и для +, оператор / будет продвигать обе стороны до int, поэтому он становится -106 (int), что равно -53 (int), если делиться на 2. Наконец, вы снова добавили byte, в итоге получилось -53 (byte).

В версии 2, вы разделите 150 (int) на 2, и поскольку обе стороны уже int ценности, не продвижение по службе не будет сделано, в конечном итоге с 75 (int). Кастинг, который до byte дает вам 75 (byte). Отсутствие переполнения.

+0

О, это была моя интуиция. не знал, что операторы работают только с int. черт возьми, вы, Ява. lol Спасибо @ Andreas –

1

Вы литье две очень разных значений.

В вашей первой строке вы делаете две броски. Первый переполняется. Вы делаете результат low + high байтом, который переполняется в вашем случае.

Однако в вашей второй линии вы литье (low + high)/2 к byte, и предполагая, как low и high положительны, что означает, что результат r должен быть low < r < high и так как low и high может быть представлена ​​byte переменным, поэтому так может получиться результат r, и переполнения нет.

+0

, но не следует добавлять два байтовых переменных в байты, которые затем переполняются в этом случае. i.e, если низкий = 63 и высокий = 126 (оба в байте) , тогда низкий + высокий = -67 –

+1

Нет, потому что 'low + high' оценивается как сумма двух * целых чисел *, которая получается как« целое », поэтому вам нужно, чтобы бросок на 'byte' в первую очередь. –

+0

yup, понял. Спасибо @Ori Lentz –