Когда вы используете Java в сочетании с низкоуровневыми данными, например сетевые пакеты, последовательная связь, GPIO Raspberry Pi… может возникнуть некоторая путаница в числовом значении HEX-значения. Некоторое время назад на форуме Pi4J был вопрос о числовом значении, обрабатываемом как байт, который был зарегистрирован как отрицательное число -86 вместо ожидаемого значения 170. Итак, это моя попытка попытаться объяснить эту загадку ...

Основы

Очень короткий:

  • Вся логика в мозгу компьютера - это бит, который может быть 0 или 1 (выключен или включен).
  • Когда вы объединяете 8 бит, вы получаете байт.

Преобразование битов в числовое и шестнадцатеричное значение

Комбинация нескольких битов преобразуется в число с использованием степени двойки.

В повседневной жизни мы привыкли к десятичным значениям, где мы группируем все по 10, 20, 30. В программировании шестнадцатеричные значения используются больше, и они имеют диапазон от 0 до 15, что идеально соответствует максимальному значению в четыре бита («1111 »). Шестнадцатеричное значение записывается как x0 - xF.

В следующей таблице показаны все возможные комбинации 4-х битов от «0000» до «1111»:

Вычислить байтовое значение

Байт состоит из 8 бит и имеет диапазон от 0x00 (= 0) до 0xFF (= 255). Поэтому нам нужно расширить приведенную выше таблицу до 8 бит. Возьмем несколько примеров:

Ценности в Java

Давайте посмотрим на Java, как значения представлены с помощью следующего кода:

class PrintLimits {
    public static void main(String[] args) {
        System.out.println("Byte");
        System.out.println("    Min: " + Byte.MIN_VALUE);
        System.out.println("    Max: " + Byte.MAX_VALUE);
        System.out.println("Short");
        System.out.println("    Min: " + Short.MIN_VALUE);
        System.out.println("    Max: " + Short.MAX_VALUE);
        System.out.println("Integer");
        System.out.println("    Min: " + Integer.MIN_VALUE);
        System.out.println("    Max: " + Integer.MAX_VALUE);
        System.out.println("Long");
        System.out.println("    Min: " + Long.MIN_VALUE);
        System.out.println("    Max: " + Long.MAX_VALUE);
    }
}

В результате получаем такие значения:

Byte
    Min: -128
    Max: 127
Short
    Min: -32768
    Max: 32767
Integer
    Min: -2147483648
    Max: 2147483647
Long
    Min: -9223372036854775808
    Max: 9223372036854775807

Хм, это неожиданно! Байт имеет диапазон от -128 до 127, а не от 0 до 255 ?! Чтобы понять это, нам нужно знать разницу между знаковыми и беззнаковыми значениями.

Подписанный против беззнакового

Когда вы вычисляете значение байта для значения числа со знаком, старший бит (самый левый) обрабатывается как индикатор для отрицательного числа (1) или положительного числа (0), например 8 битов «1000 1111»:

«1000 1111» равно -15 и 143 в зависимости от того, обрабатываете ли вы его как подписанный или неподписанный.

То же самое касается короткого кода, который состоит из двух байтов (= 16 бит), например «1000 0000 0000 1111»:

«1000 0000 0000 1111» равно -15 и 32,783 в зависимости от того, обрабатываете ли вы его как подписанный или беззнаковый.

Заключение

Вы должны быть уверены, как вы обрабатываете числовые значения при их чтении, чтобы не путать знаковое и беззнаковое значение!

К счастью, у нас есть функция Byte.toUnsignedInt (b), чтобы убедиться, что мы считываем правильное значение при регистрации значений. Вот небольшая демонстрация со значением 170 из исходного вопроса форума Pi4J:

class HexIntegerToString {
    public static void main(String[] args) {
        convertByte((byte) 170);
    }
    private static void convertByte(byte value) {        
        System.out.println("Byte Unsigned: "
           + Byte.toUnsignedInt(value) + "\tSigned: " + value);
        System.out.println("    Hex value:  0x" 
           + Integer.toHexString(value & 0xFF));
        System.out.println("    Binair:     " 
           + Integer.toBinaryString(value & 0xFF));
    }
}

Что дает этот результат:

Byte Unsigned: 170      Signed: -86
    Hex value:  0xaa
    Binair:     10101010

Если вы хотите поэкспериментировать с приложением JavaFX для преобразования битов в числовые значения, как вы можете видеть на скриншотах выше, отметьте исходники в этом проекте на GitHub.

Другие статьи, которые могут вам понравиться: