Ошибка Java: возможная потеря точности

Я делаю небольшую программу на Java, которая шифрует файлы любого типа. Я делаю это следующим образом: я открываю входной файл, читаю его в массиве байтов того же размера, что и этот файл, затем выполняю кодирование и записываю весь массив в файл .dat с именем output. дат. Для индексации массива байтов я использую переменную типа int. Код:

        for(int i : arr) {
            if(i>0) {
                arr[i] = arr[i-1]^arr[i];
            }
        }

«arr» — это массив байтов того же размера, что и входной файл.

Я получаю ошибку: CodingEvent.java:42: ошибка: возможная потеря точности

обр [я] = обр [я-1] ^ обр [я];

(стрелка указывает на оператор ^)

требуется: байт

найдено: целое

Что случилось? Не могли бы вы мне помочь, пожалуйста?


person mpeter    schedule 16.07.2013    source источник


Ответы (4)


Результатом byte ^ byte, как ни странно, является int. Используйте приведение к результату выражения при присвоении его обратно arr[i]:

arr[i] = (byte)(arr[i-1]^arr[i]);

Это связано с тем, что оператор определен как выполняющий двоичное числовое продвижение в своих операндах, и что он на самом деле делает (в данном случае):

arr[i] = (int)arr[i-1]^(int)arr[i];

... что естественно приводит к int. Вот почему нам нужен актерский состав.

person T.J. Crowder    schedule 16.07.2013

Операнды операторов ^ сначала конвертируется в int (это называется двоичным числовым продвижением). Таким образом, оба byte (arr[i-1] и arr[i]) преобразуются в int, и результатом операции также является int.

Вам нужно привести результат обратно к byte, чтобы назначить его arr[i].

person assylias    schedule 16.07.2013
comment
РЖУ НЕ МОГУ! Мы оба ссылались на двоичное числовое преобразование. Это слишком гиковски. - person T.J. Crowder; 16.07.2013

Если arr[] имеет тип byte[], то это проблема, когда java выполняет любую бинарную операцию с целыми числами, она возвращает int или long в зависимости от операторов. В этом случае результатом arr[i-1]^arr[i] является int, который вы пытаетесь сохранить в байте. >.

person morgano    schedule 16.07.2013

Посмотрите JLS 15.22.1< /а>

Когда оба операнда оператора &, ^ или | имеют тип, преобразуемый (§5.1.8) в примитивный целочисленный тип, сначала выполняется двоичное числовое преобразование операндов (§5.6.2).

И JLS 5.6.2< /а>

1. Если какой-либо операнд имеет ссылочный тип, он подвергается преобразованию распаковки (§5.1.8).

2. Расширение примитивного преобразования (§5.1.2) применяется для преобразования одного или обоих операндов в соответствии со следующими правилами:

  1. Если один из операндов имеет тип double, другой преобразуется в double.

  2. В противном случае, если один из операндов имеет тип float, другой преобразуется в float.

  3. В противном случае, если один из операндов имеет тип long, другой преобразуется в long.

  4. В противном случае оба операнда преобразуются в тип int.

Следовательно, приведенное ниже выражение сначала преобразуется в int .

arr[i-1]^arr[i];

Чтобы вернуть его к byte , используйте явное приведение:

arr[i] = (byte)(arr[i-1]^arr[i]);
person AllTooSir    schedule 16.07.2013