Целое число без знака в Java

Я пытаюсь реализовать существующий сетевой протокол, который активно использует типы данных Unsigned, которые не поддерживаются Java. Что я сейчас делаю, так это для каждого типа данных выбираю следующий больший, чтобы беззнаковое число могло поместиться в положительную область, а затем использую сдвиг байтов для получения желаемого эффекта. Поскольку это довольно подвержено ошибкам, и для unsigned long вперед мне приходится использовать BigInteger, который намного тяжелее, чем расширенные типы, мне было интересно, нет ли лучшего способа добиться этого?


person cdecker    schedule 15.12.2010    source источник


Ответы (1)


В зависимости от того, что вы делаете, вы можете просто рассматривать long как 64-битное значение, а int как 32-битное значение. Большинство операций esp readInt/Long writeInt/Long работают точно так же, игнорируя знак.

Можете ли вы привести пример операции, которую вы выполняете с этими числами, и, возможно, мы можем предложить, как сделать то же самое, не расширяя тип.

Например, ++, --, +, -, *, ==, !=, ‹‹ работают одинаково независимо от знака (т. е. дают один и тот же ответ). вместо >> можно заменить >>>

Это /, %, >, >=, ‹, ‹= и функции печати, которые принимают значения со знаком, но вы должны иметь возможность обойти их (если вы их используете).

e.g.

long unsignedA = 
long unsignedB = 
boolean greater = unsignedA + Long.MIN_VALUE > unsignedB + Long.MIN_VALUE

РЕДАКТИРОВАТЬ: Почему это работает? Отчасти потому, что в java нет исключений переполнения/недополнения.

e.g.

byte unsignedA = 0;
unsignedA--; 
// unsignedA == FF, is this -1 or 255? Java assumes the former but you assume the later

byte unsignedB = unsignedA * unsignedA;
// unsignedB is -1 * -1 = 1 or (byte) (255*255) = (byte) 65525 = 1.
person Peter Lawrey    schedule 15.12.2010
comment
Хм, это звучит многообещающе, я надеялся просто создать InputStream и оттуда просто работать со значениями, как и ожидалось, вместо того, чтобы перетаскивать их в программе. Проблема в том, что по большей части они представляют собой IP-адреса, номера версий (очень тяжелые для ›, ‹, ‹= и ›=), криптохэши (вероятно, нет проблем) и временные метки (опять же тяжелые для сравнений). - person cdecker; 15.12.2010
comment
Для IP-адресов вам нужно будет использовать трюк с baising или расширить до long. для длинных временных меток вы должны иметь возможность предположить, что они находятся в диапазоне от 0 до Long.MAX_VALUE, если они указаны в миллисекундах. Используют ли ваши номера версий верхний бит? Можете ли вы привести пример того, который делает? (если это так, вам также нужно сместить сравнение) - person Peter Lawrey; 15.12.2010
comment
Длинные миллисекундные временные метки со знаком ограничены 292 471 208 годом, если вы начинаете с 1 г. до н.э. (0-го года не было), - person Peter Lawrey; 15.12.2010
comment
К сожалению, я не могу изменить сам протокол, но вы правы в том, что я могу просто игнорировать старшие биты в метках времени (они указаны в секундах с 01.01.1970...). Да, парень, разработавший протокол, сделал действительно плохой выбор :-) - person cdecker; 15.12.2010
comment
@cdecker, так что, если вы проигнорируете верхний бит в течение нескольких секунд, вы все равно можете перейти к 293 миллиардам лет, учитывая, что солнцу осталось жить всего 6 миллиардов лет ... ;) Смещение даты к 1970 году было довольно бессмысленным. ;) У него могло бы быть не микросекунд с 1 г. до н.э., и у вас все равно не было бы проблем, я подозреваю. - person Peter Lawrey; 15.12.2010
comment
@PeterLawrey Как мы можем, например, сдвинуть длинное значение без знака? (Изображение. Я пытаюсь сохранить 64-битное целочисленное значение в 8-байтовом массиве) - person ; 26.02.2013
comment
@Desolator Вы можете использовать >>> для смещения битов без знака. - person Peter Lawrey; 06.03.2013