Подход, который вы выберете, будет зависеть от возможного диапазона значений.У вас наверняка есть некоторые внутренние знания о возможном диапазоне, и вас могут интересовать только преобразования в более узком диапазоне.
Итак, предположим, что вас интересует только целочисленное значение.В этом случае я бы просто присвоил число int
или long
, и в этот момент проблема становится достаточно очевидной.
Или предположим, что диапазон не будет включать в себя какие-либо большие показатели, но выинтересует несколько цифр дроби.Чтобы получить три цифры дроби, я мог бы сказать int x = f * 1000;
, преобразовать x, а затем вставить десятичную точку как строковую операцию.
Если все вышеперечисленное не выполнено, число с плавающей запятой или двойное число имеет бит знака,дробь и показатель степени.Во фракции скрыт 1
.(Числа нормализуются до тех пор, пока у них нет начальных нулей, после чего они делают еще один сдвиг, чтобы получить дополнительный бит точности.) Затем число равно дроби (плюс начальный «1») * 2 ** экспонента,Практически во всех системах, использующих представление IEEE 754, вы можете просто использовать эту страницу Википедии IEEE 754 , чтобы понять формат.Это не , что отличается от простого преобразования целого числа.
Для одинарной точности, как только вы получите экспоненту и дробь, значение Примечание 1 от числа равно (frac / 2 23 + 1) * 2 exp или frac * 2 exp - 23 + 2 exp .
Вот пример, который должен помочь вам начать полезное преобразование:
$ cat t.c
#include <stdio.h>
void xconvert(unsigned frac)
{
if (frac) {
xconvert(frac / 10);
printf("%c", frac % 10 | '0');
}
}
void convert(unsigned i)
{
unsigned sign, exp, frac;
sign = i >> 31;
exp = (i >> (31 - 8)) - 127;
frac = i & 0x007fffff;
if (sign)
printf("-");
xconvert(frac);
printf(" * 2 ** %d + 2 ** %d\n", exp - 23, exp);
printf("\n");
}
int main(void)
{
union {
float f;
unsigned i;
} u;
u.f = 1.234e9;
convert(u.i);
return 0;
}
$ ./a.out
1252017 * 2 ** 7 + 2 ** 30
Примечание 1. В этом случае дробь преобразуется так, как если бы двоичная точка была навместо левого, с корректирующими корректировками, а затем с показателем степени и скрытого бита.