There is a "portable" way. Using frexpf():
Code:
float m;
int e;
m = frexpf( value, &e );
printf( "Value=%f -> m=%f, e=%d\n", value, m, e );
frexpf() returns values between 0<=m<1, and e is the actual expoent plus 1. So, if you want the actual expoent and mantissa for normalized values:
Code:
m = frexpf( f, &e );
m *= 2.0;
--e;
But, of couse, be careful with zero, NAN and INFINITY.
Here's a simple test with floats:
Code:
#include <stdio.h>
#include <math.h>
void showfloat ( float f )
{
float m;
int e;
printf( "value=%g ", f );
// Zero, NAN and INFINITY are special (known expoent).
if ( f == 0.0f || ! isfinite ( f ) )
{
printf ( "- Special case.\n" );
return;
}
m = frexpf ( f, &e );
printf ( " (mantissa=%.28g, expoent=%d).\n",
m * 2.0, --e );
}
int main ( void )
{
int n;
float minimum, maximum;
n = 1;
minimum = * ( float * ) &n; // minimum subnormal possible.
n = 0x7f7fffff;
maximum = * ( float * ) &n; // maximum positive normalized possible.
float values[] = { 0.0f,
1.0f,
-1.0f,
minimum,
maximum,
NAN,
INFINITY };
for ( int i = 0;
i < sizeof values / sizeof values[0];
i++ )
showfloat ( values[i] );
}
Code:
$ cc -O2 -o test test.c -lm
$ ./test
value=0 - Special case.
value=1 (mantissa=1, expoent=0).
value=-1 (mantissa=-1, expoent=0).
value=1.4013e-45 (mantissa=1, expoent=-149).
value=3.40282e+38 (mantissa=1.99999988079071044921875, expoent=127).
value=nan - Special case.
value=inf - Special case.