2015-08-27 4 views
2

Я хотел бы реализовать следующий псевдокод, где a является байтом, а b является байтом.Как использовать modulo с подписанными байтами?

(a + b) mod 256 

Я буду писать в Scala, как следующие фрагменты кода, но я не думаю, что будет существенная разница в Java.

Таким образом, если значения байтов в диапазоне от 0 до 255 (включительно) я мог бы написать:

(a + b) % 256 

Но Java/Scala тип Byte подписан и находится в диапазоне от -128 до 127 (включительно). Я мог бы написать:

def f1(a: Byte, b: Byte): Byte = (((a + 128 + b + 128) % 256) - 128).toByte 

Это кажется излишне сложным для меня, но я не знаю, как % ведет себя на отрицательные значения. Также я не знаю, можно ли упростить эту функцию с помощью xor или что-то в этом роде.

Как я могу реализовать и упростить функцию, основанную на типе Byte?

или более общий:

Как использовать по модулю с подписанными байт?

РЕДАКТИРОВАТЬ:

Функция f1 сверху не является правильным. Должно быть:

def f1(a: Byte, b: Byte): Byte = ((a + b + 128) % 256 - 128).toByte 

Из-за этого мое сравнение с упрощенными версиями было неправильным. Так что это упрощенный способ должен работать:

def f2(a: Byte, b: Byte): Byte = (a + b).toByte 

два значения преобразуются в Int значений неявно и суммируются. При преобразовании его обратно в Byte первые 3 из 4 байтов полученного Int будут обрезаны, , который равен по модулю операции. Теперь функции f1 и f2 возвращают равные результаты. Протестировано со всеми 256 * 256 возможными вариантами ввода.

+0

бы вернуть ваш метод значение вашего ожидаете? Например, если результат вашего 'mod' превышает 128, вы все равно получите отрицательный номер. – fdsa

+0

Да, я ожидаю, что отрицательные значения будут возвращены в некоторых случаях. Я думаю, что с двоичной точки зрения все равно, но в контексте подписанного типа «Byte» наиболее значимый бит интерпретируется как знак значения. Я думаю, 0 => + и 1 => -. – user573215

+0

Я подозреваю, что вы хотите, эквивалентно '& 0xFF'. –

ответ

0

Это упрощенная версия:

def f2(a: Byte, b: Byte): Byte = (a + b).toByte 

Я редактировал вопрос и объяснил там ответ, потому что я сделал ошибку, которая была включена в этом вопросе.

0

В Java оператор модуль % может давать либо 0 или номер одного и того же знака, что и дивиденд:

-1 % 256 = -1. 

Кроме того, даже с подписью byte типа в Java, битовый образ всегда может быть истолковано как значение без знака.

100000000 = -128 (signed) = 128 (signed) 

Кроме того, выполняя byte арифметика по модулю 256 является излишним, так как литье обратно в byte выполняет это неявно.

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

public static void addMod256(byte a, byte b) 
{ 
    byte c = (byte) (a + b); 
    System.out.println("(" + a + " + " + b + ") % 256 = " + c + 
     ". Unsigned: (" + 
     (a & 0xFF) + " + " + (b & 0xFF) + ") % 256 = " + (c & 0xFF) + "."); 
} 

addMod256((byte) 6, (byte) 70);  // No overflow in signed or unsigned bytes 
addMod256((byte) 70, (byte) 70); // Overflow only in signed bytes 
addMod256((byte) -6, (byte) -70); // Overflow only in unsigned bytes 
addMod256((byte) -120, (byte) -120);// Overflow in both signed and unsigned bytes 

Выход:

(6 + 70) % 256 = 76. Unsigned: (6 + 70) % 256 = 76. 
(70 + 70) % 256 = -116. Unsigned: (70 + 70) % 256 = 140. 
(-6 + -70) % 256 = -76. Unsigned: (250 + 186) % 256 = 180. 
(-120 + -120) % 256 = 16. Unsigned: (136 + 136) % 256 = 16. 

Результаты не являются правильными, независимо от того, что переполнение условие присутствует. Итак, на Java вы можете просто добавить их и вернуть результат обратно в byte.

public static byte f1(byte a, byte b) 
{ 
    return (byte) (a + b); 
} 

В Scala, эквивалент будет, как вы указали уже:

def f2(a: Byte, b: Byte): Byte = (a + b).toByte