Декодирование Int32 в Java для мантиссы (значащие биты) с использованием побитовой логики

#java #bit-manipulation #bitwise-operators #ieee-754

#java #битовая манипуляция #побитовые операторы #ieee-754

Вопрос:

Я знаю, что это звучит как вопрос, который задавался ранее, но в моем случае меня просят выполнить некоторую побитовую логику для значения int32 и интерпретировать его как значение с плавающей запятой, не преобразовывая значение в значение с плавающей запятой, а интерпретируя двоичное значение, связанное с ним, как значение с плавающей запятой и находя значащие биты (также известные как мантисса) в наборе. Я использую стандарт IEE-754 для преобразования.

Инструкции:

«Используйте битовую маску для выделения значащих цифр, затем используйте цикл для перебора каждой цифры, сдвигая по мере необходимости, чтобы получить их в позиции LSB, и умножая на соответствующую степень 2. Результатом будет значение с плавающей точкой без показателя степени. Не забудьте включить «скрытый» бит! Рассмотрим цикл с обратным отсчетом — обработайте его тщательно, и это позволит вам начать с LSB и проложить свой путь к MSB. «

Исходя из моего понимания этого, я создал эту мерзость

     public static float decodeSignificantDigits(int value) {
    int mask = 0x007FFFFF;
    int significantBits = value amp; mask;
    float significantDigits = 0;
    
    for (int i = -23; i <= 0; i  ) {
        if (i != 0) {
            significantDigits  = (significantBits >> 1) * Math.pow(2, i);
            
        } else {
            significantDigits  = 1 * Math.pow(2, i);
        }
        
    }
    System.out.println(significantDigits);
    return significantDigits;
}
  

Я думаю, что я на правильном пути, но я просто не могу представить, как заставить это работать правильно.

Основная идея состоит в том, чтобы пройти следующие тесты:

 @Test
void testWhenAllOnes() {
    int bits = 0b00000000011111111111111111111111;
    int bitsWithExpoentZero = 0b00111111111111111111111111111111;
    assertEquals(Float.intBitsToFloat(bitsWithExpoentZero), FloatDecoder.decodeSignificantDigits(bits), TOL);
}

@Test
void testWhenMsbOfSignificantDigitsIsOneRestZeroes() {
    int bits = 0b00000000010000000000000000000000;
    int bitsWithExpoentZero = 0b00111111110000000000000000000000;
    assertEquals(Float.intBitsToFloat(bitsWithExpoentZero), FloatDecoder.decodeSignificantDigits(bits), TOL);
}

@Test
void testWhenLsbOfSignificantDigitsIsOneRestZeroes() {
    int bits = 0b00000000000000000000000000000001;
    int bitsWithExpoentZero = 0b00111111100000000000000000000001;
    assertEquals(Float.intBitsToFloat(bitsWithExpoentZero), FloatDecoder.decodeSignificantDigits(bits), TOL);
}
  

Мне также сообщили, чтобы я не использовал Integer.toBinaryString() для моего решения.

Комментарии:

1. Math.pow(2, i) не делайте этого. Используйте 1 << i вместо

2. Лучше, некоторые из моих тестов работают сейчас. Но почему это работает?

3. Потому что это на 100% точно, а FP — нет.

4. Конечно, это очевидно, но я имею в виду, как работает сдвиг от 1 до n количества битов? Я уверен, что это глупый вопрос для кого-то опытного, но я не опытный.