Hello
If I have a FLOAT variable how to retrieve its exponent and mantissa in
the most portable way.
C doesn't have FLOAT, it does have float, and it is NOT nit-picking to
point it out because C is case-sensitive.
As has already been pointed out, what you probably want is frexpf(). In
the unlikely event that you're using a implementation where FLT_RADIX !=
2, then the frexpf() won't give you what you asked for (though it may
give you what you want). The following function will give you what you
asked for, whether or not FLT_RADIX == 2.
This code below makes extensive use of parts of the C standard library
that were new in C99; it seems absurd to have to worry about C90 when
C2011 has already come out, but the practical matter of fact is that
there's still a lot of C implementations out there which have not yet
implemented all features of C99, possible including these. ilogbf(x) can
be implemented as directly manipulating the floating point
representation of x; the closest equivalent in C90 is much less efficient.
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
static int decompose_float(
float x,
float *mantissa,
int *exponent
){
// Returns the sign of x, and sets *exponent to the same values
// that would be returned by ilogbf(x):
// FP_ILOGB0 if x is zero. Can be INT_MIN or -INT_MAX
// FP_ILOGBNAN if x is a NaN. Can be INT_MIN or INT_MAX
// INT_MAX if x is infinite.
// The value returned by ilogbf(x) therefore cannot be used to
// unambiguously distinguish these cases.
if(isnan(x))
{
*exponent = FP_ILOGBNAN;
*mantissa = x;
return 0;
}
int sign = (x > 0.0F) - (x < 0.0F);
if(isinf(x))
{
*exponent = INT_MAX;
*mantissa = INFINITY;
}
else if(sign)
{
*exponent = ilogbf(x);
*mantissa = x/powf(FLT_RADIX,*exponent)/sign;
}
else
{
*exponent = FP_ILOGB0;
*mantissa = 0.0F;
}
return sign;
}
int main(void)
{
float arr[] = {-INFINITY, -HUGE_VALF, -FLT_MAX, -10.0, -1.0, -0.1,
-FLT_EPSILON, -FLT_MIN, nanf(""), 0.0F, FLT_MIN, FLT_EPSILON,
0.1, 1.0,
10.0, FLT_MAX, HUGE_VALF, INFINITY};
for(int val=0; val < sizeof arr/sizeof *arr; val++)
{
float mantissa;
int exponent;
int sign = decompose_float(arr[val], &mantissa, &exponent);
printf("%12g = %2d*%8f*pow(%d,%d)\n",
arr[val], sign, mantissa, FLT_RADIX, exponent);
}
return 0;
}