Справочная информация:
Я играю с кодированием бит уровня (это не домашнее задание - просто интересно). Я нашел много хорошего материала в Интернете и в книге под названием Hacker's Delight, но у меня проблемы с одной из проблем онлайн.C Bit-Level Int к Float Conversion непредвиденного вывода
Он запрашивает преобразование целого числа в поплавок. Я использовал следующие ссылки в качестве ссылки на работу по проблеме:
How to manually (bitwise) perform (float)x?
How to convert an unsigned int to a float?
http://locklessinc.com/articles/i2f/
проблема и вопрос:
Я думал, что я понял, процесс достаточно хорошо (я пытался документировать процесс в комментариях), но когда я его тестирую, я не понимаю выход.
Test Cases:
float_i2f (2) возвращает 1073741824
float_i2f (3) возвращает 1077936128
Я ожидал увидеть что-то вроде 2.0000 и 3.0000.
Я где-то испортил конверсию? Я подумал, может быть, это адрес памяти, поэтому я подумал, может быть, я пропустил что-то на этапе преобразования, необходимого для доступа к фактическому числу? Или, может быть, я печатаю его неправильно? Я печать мой такой вывод:
printf("Float_i2f (%d): ", 3);
printf("%u", float_i2f(3));
printf("\n");
Но я думал, что метод печати было хорошо для беззнаковых значений в C (я привык к программированию на Java).
Спасибо за любой совет.
Код:
/*
* float_i2f - Return bit-level equivalent of expression (float) x
* Result is returned as unsigned int, but
* it is to be interpreted as the bit-level representation of a
* single-precision floating point values.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned float_i2f(int x) {
if (x == 0){
return 0;
}
//save the sign bit for later and get the asolute value of x
//the absolute value is needed to shift bits to put them
//into the appropriate position for the float
unsigned int signBit = 0;
unsigned int absVal = (unsigned int)x;
if (x < 0){
signBit = 0x80000000;
absVal = (unsigned int)-x;
}
//Calculate the exponent
// Shift the input left until the high order bit is set to form the mantissa.
// Form the floating exponent by subtracting the number of shifts from 158.
unsigned int exponent = 158; //158 possibly because of place in byte range
while ((absVal & 0x80000000) == 0){//this checks for 0 or 1. when it reaches 1, the loop breaks
exponent--;
absVal <<= 1;
}
//find the mantissa (bit shift to the right)
unsigned int mantissa = absVal >> 8;
//place the exponent bits in the right place
exponent = exponent << 23;
//get the mantissa
mantissa = mantissa & 0x7fffff;
//return the reconstructed float
return signBit | exponent | mantissa;
}
Вы должны использовать 'формат% f' спецификатор сказать' printf' интерпретировать значение как значение с плавающей точкой. Используя '% u', вы попросили его распечатать целое число без знака. Однако это может быть неопределенное поведение из-за строгого сглаживания, а также способ передачи переменных аргументов функции. Возможно, вам лучше создать переменную 'float' и использовать' memcpy', чтобы скопировать результирующие целочисленные биты непосредственно в float. Конечность все еще будет проблемой. Как глубоко ты хочешь пойти? – paddy
Это выглядит правильно (я не пошел, хотя ваши расчеты). То, что вы ищете, - это целое число без знака * эквивалент * битов, которые составляют число с плавающей точкой с одиночной точностью IEEE-754. Вы можете создать простой 'union'' float' и 'uint32_t' и проверить вывод обоих для подтверждения. –
Ваш код в порядке, хотя он не круглый, только усекает. – deamentiaemundi