Я написал программу для преобразования числа с плавающей запятой в его двоичное представление IEEE754 на C.
Любые улучшения приветствуются.
#include <stdio.h>
#include <stdlib.h>
void binary(float num) {
int n = *(int *) # //Evil bit hack from Quake3 Q_sqrt function
int size = sizeof(n) * 8;
char *s = malloc(1 + size); //A string which can hold 32 characters
s[size] = ' ';
int index = size - 1;
while(index >= 0) {
if (n & 1)
*(s + index) = '1';
else
*(s + index) = '0';
n >>= 1;
index--;
}
printf("%sn", s);
free(s);
}
int main(void) {
float num;
scanf("%f", &num);
binary(num);
}
1 ответ
Соответствие IEEE754
Компиляторы не обязаны поддерживать десятичные дроби IEEE754. Большинство реализаций это делают, но, тем не менее, лучше проверить максимальную переносимость. Если вы используете C99 или новее, макрос __STDC_IEC_559__
определяется всякий раз, когда поддерживается IEEE754.
sizeof (число)
По аналогии, int
не гарантируется, что это будет 32 бита. Компилятор гарантирует только минимальный размер 16 бит. Вы можете использовать целочисленные типы фиксированной ширины, определенные в stdint.h
т.е. uint32_t
или же int32_t
.
Использовать size_t
вместо int
Подходящий тип для sizeof
выражение size_t
. Как правило, любая переменная, представляющая размер или индекс, должна быть size_t
.
Поскольку вы не используете s
вне binary
функцию, вы можете просто выделить фиксированный массив размером 33 в стеке, а не в куче, используя malloc
.
static const size_t num_bits = 33;
char s[num_bits];
*(s + index)
это просто причудливый способ написать s[index]
. Последнее намного чище, IMO и намного проще для понимания тем, кто не знаком с арифметикой указателей.
Преимущество изменения использования стека нельзя недооценивать. Распределение памяти намного медленнее (даже просто накладные расходы на вызов функции), чем просто ссылка на пространство, которое компилятор выделил / оставил (затраты времени компиляции для удобства выполнения !!) .
— г-н Р.
Ваша формулировка о соответствии IEEE754 немного неверна. Это стандарт C, который не требует реализации для поддержки IEEE754. Однако сами компиляторы не могут выбирать, что они реализуют, они связаны тем, что ABI платформы определяет формат
float
а такжеdouble
должно быть. То же самое и с размером целочисленных типов.— Г. Сон
Хм, я не знал об этом, но это имеет смысл. Спасибо!
— Риш
@Rish Спасибо за ответ, хотя я не понимаю, почему все компиляторы не используют представление IEEE 754 для хранения
float
. Если нет, то каков наиболее распространенный способ хранения чисел с плавающей запятой или двойной точности (точнее, литералов с одинарной / двойной точностью)? Кстати, я компилирую указанную выше программу на gcc, поставляемом с ubuntu LTS.— С—