IEEE - 754 - найти признак, показатель степени, разрыв, нормализацию и т. Д. - PullRequest
2 голосов
/ 12 января 2010

Я беру 8-значное шестнадцатеричное число в качестве 754-разрядного числа с плавающей запятой IEEE и я хочу напечатать информацию об этом числе (signbit, expbits, fractbits, normalized, денормализованный, бесконечность, ноль, NAN) с плавающей точкой должен быть один.

Я прочитал о сдвиге битов, и я думаю, что это то, как я должен это делать ?. Однако я не уверен на 100%. Я понимаю, что знаковый бит находится в самой левой позиции числа. что указывает на положительный или отрицательный. Сколько мне сдвинуть его, чтобы найти каждого? я просто продолжаю сдвигать его, чтобы найти каждого? Может кто-нибудь объяснить, как мне найти каждого из них?

я бы сдвинулся на 1, чтобы найти знак? я бы сдвинулся на 8, чтобы получить показатель? я бы сдвинулся на 23, чтобы получить ГРП?

знак должен быть нулевым

Экспиты должны быть 128

фракбиты должны быть 0x00000000 Я думаю ...

если да, то как мне проверить это после смены?

это то, что у меня есть

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{

    short wordOrder = 0x0100;

int HexNumber;

printf("Hex IEEE - 754\n");



    if(wordOrder == 0x0100)
    {
    printf("\nbyte order: big-endian\n");
    }
    else
    {
    printf("byte order: little-endian\n");
    }

printf("\n>");
scanf("%x", &HexNumber);
printf("\n%#x",HexNumber);




return 0;
    }

мой ввод (scanf) о том, как я этого хочу ..

>40000000
0x40000000

что и делает ..

Ответы [ 7 ]

13 голосов
/ 12 января 2010

Для числа с одинарной точностью старший бит - это знак, следующие 8 бит - это показатель степени, а оставшиеся 23 бита - это мантисса. Итак ...

bool negative = !!(HexNumber & 0x80000000);
int exponent = (HexNumber & 0x7f800000) >> 23;
int mantissa = (HexNumber & 0x007FFFFF);

Если показатель равен 255, число равно + - бесконечность или NaN в зависимости от того, равна ли мантисса нулю (0 означает бесконечность). Если показатель степени равен нулю, то эфир имеет число + - ноль (если мантисса равна нулю) или мантисса является фактическим ненормализованным дробным значением.

Если показатель степени является чем-то еще, то в верхней части дроби есть скрытый бит, составляющий 24 бита. В этом случае фактический показатель степени можно рассчитать путем вычитания 127 из показателя степени, чтобы он находился в диапазоне от -127 до +127, степени двух показателей.

1 голос
/ 12 января 2010

& выполняет побитовое преобразование и операцию между двумя значениями. Если одно из значений является константой и имеет некоторые полезные свойства.

  A | B | A & B 
 ---+---+------- 
  0 | 0 | 0 
  0 | 1 | 0 
 ---+---+------- 
  1 | 0 | 0 
  1 | 1 | 1 

Как видно из таблицы истинности, первые две строки показывают, что если A = 0, A & B = 0. Таким образом, установка нуля в маске в некоторой позиции приводит к очистке этот бит

Последние две строки показывают, что если A = 1, A & B = B. Таким образом, помещение единицы в маску в некоторой позиции приводит к тому, что пропускает этот бит.

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

Вы можете выполнить то же упражнение с OR (|) и XOR (^) и заключить, что маска для использования с | устанавливает биты значения, где маска равна 1. ^ имеет эффект переключения битов значения, где маска равна 1.

/ * в ответ на комментарий * /

Это не показатель степени бит это поле экспоненты длиной 8 битов. Итак, если вы строите свою маску следующим образом:

0111 1111 1000 0000 0000 0000 0000 0000  (mask === 0x7F800000)
1011 1010 0101 0110 0110 1010 1001 1010  (value)
-------------------------------------------------
0011 1010 0000 0000 0000 0000 0000 0000   (result)

Здесь вы можете видеть, что все, что осталось от этой операции, это биты, составляющие поле экспоненты (а именно 01110100). Теперь, если вы хотите узнать значение поля, вам необходимо сместить результат вправо на требуемую величину. Требуемым количеством является (в общем случае) позиция с нулевым индексом младшего значащего бита поля. Для поля экспоненты необходимая величина сдвига составляет 23.

На боковой ноте вы должны быть осторожны при переходе вправо. Здесь мы можем избежать неприятностей, потому что знаем, что наша маска имеет ноль в старшем значащем бите, но если бы это было не так, было бы разумно привести наш результат к значению без знака перед смещением вправо. Если вы не получите расширение знака.

int8_t exponent = ((uint32_t) (value & 0x7F800000)) >> 23; 
// the cast is not necessary in this case because the mask has a 0 in the msb

Если вы хотите извлечь знаковый бит, этот бросок станет важным:

int8_t sign = ((uint32_t) (value & 0x80000000)) >> 31; 

(я не знаю, откуда у вас представление, что вам придется сдвинуться на 8, чтобы извлечь бит знака)

1 голос
/ 12 января 2010

В дополнение к битовому перевороту, который вы уже рассматриваете, есть некоторые библиотечные функции, которые позволяют разбирать и масштабировать числа с плавающей запятой.

Если у вас на руках float или double, вы можете использовать std::frexp() для определения его значения и (или мантиссы) и показателя степени. Показатель степени будет целым, но значение и будет действительным числом от 0,5 до 1 или нулю.

1 голос
/ 12 января 2010

Для проверки правильности кода используется апплет конвертера http://www.h -schmidt.net / FloatApplet / IEEE754.html

Я обнаружил, что апплет полезен для проверки некоторых значений.

0 голосов
/ 19 января 2010

исправленный код:

#include <stdio.h>
 #include <stdlib.h>

int main(int argc, char *argv[])
{


int HexNumber;




int a = 0x12345678;
unsigned char *c = (unsigned char*)(&a);
if (*c == 0x78)
{
  printf("\nlittle-endian\n");
}
else
{
  printf("\nbig-endian\n");
}

printf("\n>");
scanf("%x", &HexNumber);
printf("\n%#x",HexNumber);


 bool negative = !!(HexNumber & 0x80000000);
 int exponent = (HexNumber & 0x7f800000) >> 23;
 int mantissa = (HexNumber & 0x007FFFFF);


 printf("\nsignBit %d,", negative);
 printf("expbits %d,", exponent);
 printf("fractbits %#x,", mantissa);




return 0;
}
0 голосов
/ 13 января 2010

@ vicatcu, или кто-то еще это

icelated ..

Стандартное представление IEEE с плавающей запятой одинарной точности требует 32-битного слова, которое может быть представлено в виде нумерации от 0 до 31 слева направо. Первый бит является знаковым битом, следующие восемь битов являются экспонентными битами, а последние 23 бита являются дробью.

Поэтому, чтобы извлечь бит знака, мы используем соответствующую маску и сдвигаемся на 31, чтобы получить знак в конце? Кроме того, чтобы получить значение показателя степени. так как, его 8 бит в длину - мы сдвигаем 31 - 8 (23), чтобы сдвинуть его до конца? Если это правда, то мантисса не требует смещения? Также для извлечения значения мы используем маску. Эта часть меня смущает. Я думаю, что маска - это шестнадцатеричный эквивалент. Как мы можем придумать это шестнадцатеричное число? пример: int exponent = (HexNumber & 0x7f800000) СПАСИБО - я думаю, что получаю это ....

0 голосов
/ 12 января 2010

Ледяной спросил:

Может кто-нибудь объяснить, что здесь происходит? Куда мы идем с & номерами?

Оператор & является побитовым оператором AND. Шестнадцатеричные числа являются битовыми масками, применив оператор & с соответствующей маской, вы можете выделить интересующие вас биты.

...