Объявление unsigned int в Java

Есть ли способ объявить unsigned int в Java?

Или вопрос может быть сформулирован так же хорошо: Что такое эквивалент Java без знака?

Просто, чтобы рассказать вам контекст, я смотрел на реализацию Java String.hashcode(). Я хотел проверить возможность столкновения, если целое число было 32 unsigned int.

Ответ 1

В Java нет типа данных для целых чисел без знака.

Вы можете определить long вместо int, если вам нужно хранить большие значения.

Вы также можете использовать целое число со знаком, как если бы оно было без знака. Преимущество представления с двумя дополнениями состоит в том, что большинство операций (таких как сложение, вычитание, умножение и сдвиг влево) идентичны на двоичном уровне для целых чисел со знаком и без знака. Однако некоторые операции (деление, сдвиг вправо, сравнение и приведение) отличаются. Начиная с Java SE 8, новые методы в классе Integer позволяют полностью использовать тип данных int для выполнения арифметики без знака:

В Java SE 8 и более поздних версиях вы можете использовать тип данных int для представления 32-разрядного целого без знака, которое имеет минимальное значение 0 и максимальное значение 2 ^ 32-1. Используйте класс Integer, чтобы использовать тип данных int как целое число без знака. Статические методы, такие как compareUnsigned, divideUnsigned и т.д., Были добавлены в класс Integer для поддержки арифметических операций для целых чисел без знака.

Обратите внимание, что переменные int по-прежнему подписаны при объявлении, но теперь возможна арифметика без знака с помощью этих методов в классе Integer.

Ответ 3

Является ли значение в int подписанным или неподписанным, зависит от того, как интерпретируются биты - Java интерпретирует биты как знаковое значение (у него нет неподписанных примитивов).

Если у вас есть int, который вы хотите интерпретировать как значение без знака (например, вы читаете int из DataInputStream, который, как вы знаете, содержит неподписанное значение), вы можете сделать следующий трюк.

int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffl;

Обратите внимание, что важно, чтобы шестнадцатеричный литерал был длинным литералом, а не int literal - следовательно, "l" в конце.

Ответ 4

Нам нужны неподписанные числа для моделирования MySQL unsigned TINYINT, SMALLINT, INT, BIGINT в jOOQ, поэтому мы создали jOOU, минималистскую библиотеку, предлагающую типы обертки для целых чисел без знака в Java. Пример:

import static org.joou.Unsigned.*;

// and then...
UByte    b = ubyte(1);
UShort   s = ushort(1);
UInteger i = uint(1);
ULong    l = ulong(1);

Все эти типы расширяются java.lang.Number и могут быть преобразованы в примитивные типы более высокого порядка и BigInteger. Надеюсь, это поможет.

(Отказ от ответственности: я работаю в компании за этими библиотеками)

Ответ 5

Для чисел без знака вы можете использовать эти классы из библиотеки Guava:

Они поддерживают различные операции:

  • плюс
  • минус
  • раз
  • мод
  • dividedBy

В данный момент, похоже, не хватает операторов сдвига байтов. Если вам это нужно, вы можете использовать BigInteger из Java.

Ответ 6

Используйте char для 16-разрядных целых чисел без знака.

Ответ 7

Похоже, что вы можете справиться с проблемой подписывания, выполнив "логическое И" над значениями перед их использованием:

Пример (значение byte[] header[0] равно 0x86):

System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));

Результат:

Integer -122 = 134

Ответ 8

Возможно, это то, что вы имели в виду?

long getUnsigned(int signed) {
    return signed >= 0 ? signed : 2 * (long) Integer.MAX_VALUE + 2 + signed;
}
  • getUnsigned(0) → 0
  • getUnsigned(1) → 1
  • getUnsigned(Integer.MAX_VALUE) → 2147483647
  • getUnsigned(Integer.MIN_VALUE) → 2147483648
  • getUnsigned(Integer.MIN_VALUE + 1) → 2147483649

Ответ 9

Просто сделал этот кусок кода, который преобразует "this.altura" с отрицательного на положительное. Надеюсь, это поможет кому-то в этом нуждаться.

       if(this.altura < 0){    

                        String aux = Integer.toString(this.altura);
                        char aux2[] = aux.toCharArray();
                        aux = "";
                        for(int con = 1; con < aux2.length; con++){
                            aux += aux2[con];
                        }
                        this.altura = Integer.parseInt(aux);
                        System.out.println("New Value: " + this.altura);
                    }

Ответ 10

Здесь есть хорошие ответы, но я не вижу демонстрации побитовых операций. Как говорит Visser (в настоящее время принятый ответ), Java по умолчанию подписывает целые числа (Java 8 имеет целые числа без знака, но я никогда не использовал их). Без дальнейших церемоний, давайте сделаем это...

Пример RFC 868

Что произойдет, если вам нужно записать целое число без знака в IO? Практический пример - когда вы хотите вывести время в соответствии с RFC 868. Для этого требуется 32-разрядное целое число без знака с прямым порядком байтов, которое кодирует количество секунд с 12:00 утра. 1 января 1900 года. Как бы вы это закодировали?

Создайте свое собственное 32-разрядное целое число без знака, например:

Объявить байтовый массив из 4 байтов (2 ^ 31 бит)

Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)

Теперь вам нужно заполнить каждый байт в массиве информацией в порядке с прямым порядком байтов (или с прямым порядком байтов, если вы хотите разрушить хаос). Предполагая, что у вас есть long, содержащее время (длинные целые числа имеют длину 64 бита в Java), называемое secondsSince1900 (в котором используются только первые 32 бита, и вы обработали тот факт, что Date ссылается на 12:00 AM 1 января 1970 г.), то вы можете использовать логическое "И" для извлечения битов из него и смещения этих битов в позиции (цифры), которые не будут игнорироваться при приведении к байту и в порядке с прямым порядком байтов.

my32BitUnsignedInteger[0] = (byte) ((secondsSince1900 & 0x00000000FF000000L) >> 24); // first byte of array contains highest significant bits, then shift these extracted FF bits to first two positions in preparation for coersion to Byte (which only adopts the first 8 bits)
my32BitUnsignedInteger[1] = (byte) ((secondsSince1900 & 0x0000000000FF0000L) >> 16);
my32BitUnsignedInteger[2] = (byte) ((secondsSince1900 & 0x000000000000FF00L) >> 8);
my32BitUnsignedInteger[3] = (byte) ((secondsSince1900 & 0x00000000000000FFL); // no shift needed

Наш my32BitUnsignedInteger теперь эквивалентен беззнаковому 32-разрядному целому числу с прямым порядком байтов, который соответствует стандарту RCF 868. Да, длинный тип данных подписан, но мы проигнорировали этот факт, потому что предполагали, что секундаSince1900 использовала только младшие 32 бита). Из-за перевода длинного в байт все биты, превышающие 2 ^ 7 (первые две цифры в шестнадцатеричном формате), будут игнорироваться.

Источник ссылки: Java Network Programming, 4-е издание.

Ответ 11

Вы можете использовать функцию Math.abs(число). Он возвращает положительное число.