Decomposing a FLOAT

R

Raj Pashwar

Hello

If I have a FLOAT variable how to retrieve its exponent and mantissa in
the most portable way.

Cheers Raj
 
B

Ben Bacarisse

Steven G. Kargl said:

That's probably what the OP wants, but it's not what they asked for!
frexpf returns a normalised fraction, not the mantissa itself, and the
power returned is always given as a power of 2, even on machines that
use some other radix for the exponent.
 
I

Ike Naar

Hello

If I have a FLOAT variable how to retrieve its exponent and mantissa in
the most portable way.

You could have a look at the frexp function from <math.h>
 
J

James Kuyper

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;
}
 
J

Joe keane

C doesn't have FLOAT, it does have float, and it is NOT nit-picking to
point it out because C is case-sensitive.

damn

cut the guy a break

sometimes i think this newsgroup is 'comp.lang.nitprick'

he asked the question in English

just as a guess English not his native language

is kind of rude
 
M

Malcolm McLean

בת×ריך ×™×•× ×©×‘×ª,2 ביוני 2012 00:02:46 UTC+1, מ×ת Joe keane:
FLOAT is likely to be a typedef, and the probable reason for using it is totoggle the underlying types without changing the code. So the answer to the question is different.
 
K

Kenny McCormack

damn

cut the guy a break

sometimes i think this newsgroup is 'comp.lang.nitprick'

he asked the question in English

just as a guess English not his native language

is kind of rude

Welcome to CLC. We hope you enjoy your stay...
 
J

Joe keane

Welcome to CLC. We hope you enjoy your stay...

i listened to Pind Floyd a lot of times

i still don't think

i had a lot of cowerkers
who has English is not perfect

the other hand
my speaking to them in their native language is somewhere between
impossible or more impossible, probably the latter
 
J

James Kuyper

בת×ריך ×™×•× ×©×‘×ª, 2 ביוני 2012 00:02:46 UTC+1, מ×ת Joe keane:
FLOAT is likely to be a typedef, and the probable reason for using it is to toggle the underlying types without changing the code. So the answer to the question is different.

I doubt it was a typedef, I think it was just a failure to be adequately
aware of C's case-sensitivity. He may be more familiar with some other
language that is case-insensitive.
However, if it was a typedef, you're right - without knowing what it's a
typedef for, it would be impossible to answer the question.
 
N

Nobody

I doubt it was a typedef, I think it was just a failure to be adequately
aware of C's case-sensitivity.

Or maybe it's just a case of conventional usage of capitals as a form of
emphasis (you can't use boldface in plain text and using HTML on usenet is
frowned upon). In much the same way that posters often use quotes without
necessarily meaning a C string literal.
 
K

Keith Thompson

Nobody said:
Or maybe it's just a case of conventional usage of capitals as a form of
emphasis (you can't use boldface in plain text and using HTML on usenet is
frowned upon). In much the same way that posters often use quotes without
necessarily meaning a C string literal.

Whatever the OP meant, I hope he understands by now that referring to
the type "float" as "FLOAT" is not a good idea.
 
R

Raj Pashwar

Whatever the OP meant, I hope he understands by now that referring to
the type "float" as "FLOAT" is not a good idea.

Yes, thanks :)

In fact John Kupyer was right : on my system FLOAT is a type-def for long
double.

Cheers Raj
 
E

Eric Sosman

Yes, thanks :)

In fact John Kupyer was right : on my system FLOAT is a type-def for long
double.

In that case, don't use frexpf(): Use frexpl() instead, or
#include <tgmath.h> and use frexp().
 
J

James Kuyper

Yes, thanks :)

In fact John Kupyer was right : on my system FLOAT is a type-def for long
double.

John's my brother, and we both spell it Kuyper, not Kupyer. No offense
taken, but a programmer needs to be a bit more careful about details
like that, or the programs won't work. There will, of course, per
tradition, be at least one spelling error in this message, even though I
didn't put one in deliberately. :-}

The example code I provided was based upon the assumption that FLOAT
meant float; that's a perfectly natural assumption, which is why it's a
bad idea to define a typedef with that name; a more neutral name such as
FP_TYPE would be better; a name that indicated the domain of
applicability of the typedef would be even better. For example, one of
third-party libraries I use chose PGS as it's identifying prefix, and
PGSt_integer is their typedef for the integer type to be used when
interfacing with their library.

Since FLOAT was a typedef for long double, the example code I provided
needs modification as follows:

1. Replace float with FLOAT
2. Remove the F suffixes on floating point constants.
3. Replace FLT prefixes on macros from the standard library with LDBL.
4. Replace INFINITY inside decompose_FLOAT() with x/sign.
5a. Replace f suffixes on standard math library functions with l.
or
5b. #include <tgmath.h> and remove the f suffixes from the standard math
library functions.

Note: if there's any chance that FLOAT might be a typedef for a
different type in the future, or on some other platform where this code
needs to work, 4b is to be preferred to 4a. Item 3 needs to be changed
accordingly; but that is relevant only in the test driver.
 
M

Malcolm McLean

בת×ריך ×™×•× ×¨×שון, 3 ביוני 2012 13:51:42 UTC+1, מ×ת James Kuyper:
On 06/03/2012 04:11 AM, Raj Pashwar wrote:

The example code I provided was based upon the assumption that FLOAT
meant float; that's a perfectly natural assumption, which is why it's a
bad idea to define a typedef with that name; a more neutral name such as
FP_TYPE would be better;

int fft(FLOAT *real, FLOAT *imaginary, int N)

is obvious

IS_TYPE fft_fpt(FP_TYPE *r, FP_TYPE *j, IU_TYPE i)

much less so. You have a certain amount of redundancy. Choose a bad symbol for one thing and code is still very readable. It's the accumulation of little obscurities which is the killer.
 
J

James Kuyper

בת×ריך ×™×•× ×¨×שון, 3 ביוני 2012 13:51:42 UTC+1, מ×ת James Kuyper:

int fft(FLOAT *real, FLOAT *imaginary, int N)

is obvious

The obvious implication of that typedef is wrong (seriously so, as it
turns out), so it's obviousness is a mark against it.
IS_TYPE fft_fpt(FP_TYPE *r, FP_TYPE *j, IU_TYPE i)

much less so. You have a certain amount of redundancy. Choose a bad symbol for one thing and code is still very readable. It's the accumulation of little obscurities which is the killer.

In suggesting FP_TYPE, I was merely trying to keep as close as possible
to the style of the OP's code as I could, while making my point. I
personally think that IS_TYPE and IU_TYPE are both substantially less
clear than FP_TYPE.

My preferred alternative is fairly well exemplified the the third party
library I was talking about. It would use PGSt_integer, PGSt_double, and
PGSt_uinteger for the places where you used IS_TYPE, FP_TYPE, and
IU_TYPE. Shortening "_TYPE" to "t_" is an improvement; tagging the types
with PGS to indicate which library they were associated with was another
improvement, and using relatively long names for the specific types
helps clarify things too.

I think that using "double" in the type name was a bad choice for the
same reason I originally gave against "FLOAT", but nobody's perfect.
 
K

Keith Thompson

Raj Pashwar said:
Yes, thanks :)

In fact John Kupyer was right : on my system FLOAT is a type-def for long
double.

(James Kuyper)

Out of curiosity, where exactly does this typedef (not "type-def")
appear? Is it in a header for some particular application or
library, or is it really defined by your (operating) system?

FLOAT is a really bad name for a typedef. Either it's a typedef
for the built-in type "float", in which case it's fairly useless,
or it's a typedef for something other than "float", in which case
it's actively misleading.

(The only reasonable justification I can think of is that FLOAT
might be used to implement a type in some other language.)
 
R

Raj Pashwar

(James Kuyper)

Out of curiosity, where exactly does this typedef (not "type-def")
appear? Is it in a header for some particular application or library,
or is it really defined by your (operating) system?

FLOAT is a really bad name for a typedef. Either it's a typedef for the
built-in type "float", in which case it's fairly useless, or it's a
typedef for something other than "float", in which case it's actively
misleading.

(The only reasonable justification I can think of is that FLOAT might be
used to implement a type in some other language.)

Yes, it's in one of the headers.

I think the idea is: it gives flexibility to change between float (=small
size, low precision) or long double (=high size, high precision) or
double (=compromise) at a later stage, without needing to change all
definitions everywhere in code : only the typeDef needs changing.

Cheers Raj
 
R

Raj Pashwar

In that case, don't use frexpf(): Use frexpl() instead, or
#include <tgmath.h> and use frexp().

Thanks. I've never used the tgmath library before - can you give me any
pointers where to download it? What are the advantages over the standard
math library?

Cheers Raj
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top