#include <inttypes.h>
#include <float.h>
#include <string.h>
#include <stdio.h>
typedef signed char schar;
typedef unsigned char uchar;
typedef unsigned long ulong;
typedef signed long long sllong;
typedef unsigned long long ullong;
typedef union sfpn
{
float fpn;
uchar raw;
struct
{
ullong man:23;
ullong exp:8;
ullong sig:1;
};
} sfpn;
sfpn
fpn_make (ulong base, ullong num, ullong fpn, long exp, long dig)
{
sfpn mine = { 0 };
long exp_max = FLT_MAX_EXP, pos = 0, pos_max = 23;
ullong one = 1, NUM;
if (dig < 1)
return mine;
if (num)
{
for (NUM = num; NUM; NUM /= base, --dig);
for (NUM = num; NUM > 1 && pos < pos_max; NUM >>= 1, ++pos);
for (; one <= fpn; one *= base, --dig);
for (; dig > 0; one *= base, --dig);
}
else if (fpn)
{
for ( --dig; one <= fpn; one *= base, --dig );
for ( pos = -4; dig > 0; one *= base, --dig, pos -= 3 );
}
else return mine;
if ( exp ) {
printf("exp = %ld ", exp );
if ( exp > 0 )
pos += (exp * 2);
else
pos += (exp * 4);
mine.exp = exp_max + pos;
}
else
mine.exp = exp_max + (pos - 1);
mine.man = num;
for (NUM = fpn; pos < pos_max; ++pos)
{
NUM *= 2;
mine.man <<= 1;
if (NUM >= one)
{
mine.man |= 1;
NUM -= one;
}
}
NUM *= 2;
if ( NUM >= one ) mine.man |= 1;
return mine;
}
int fpn_read (char *text);
char *fpn_text[] = {
"0",
"1", "10", "100", "101",
"1.1", "1.01", "1.001", "1.101",
"0.1", "0.01", "0.001", "0.101",
"1e+1", "1e+10", "1e+100",
"1e-1", "1e-10", "1e-100",
NULL
};
int main ()
{
size_t i = 0;
while (fpn_text[i] && i < 15)
fpn_read (fpn_text[i++]);
return 0;
}
int fpn_read (char *text)
{
char *_text = text;
ulong base = 10;
long exp = 0, dig = 0;
ullong num = 0, fpn = 0;
sfpn test = { 0 }, mine = { 0 };
sscanf (text, "%f", &(test.fpn));
while (*text == '0')
++text;
for (; *text >= '0' && *text <= '9'; ++text)
{
num *= base;
num += (*text - '0');
++dig;
}
if (dig < 1)
dig = 1;
if (*text == '.')
{
for (++text; *text >= '0' && *text <= '9'; ++text)
{
fpn *= base;
fpn += (*text - '0');
++dig;
}
}
if (*text == 'e' || *text == 'E')
{
if (*(++text) == '-')
{
for (++text; *text >= '0' && *text <= '9'; ++text)
{
exp *= base;
exp -= (*text - '0');
}
}
else
{
for (++text; *text >= '0' && *text <= '9'; ++text)
{
exp *= base;
exp += (*text - '0');
}
}
}
mine = fpn_make (base, num, fpn, exp, dig);
printf ("man t = %06X m = %06X ", test.man, mine.man);
printf ("exp t = %02X m = %02X ", test.exp, mine.exp);
printf ("sig t = %u m = %u\n", test.sig, mine.sig);
printf ("fpn t = %e m = %e, ", test.fpn, mine.fpn);
printf ("text = '%s'\n", _text);
return 0;
}