components of a floating point value



 DEVELOP > C > components of a floating point value

LINK TO THIS PAGE  


rating :  0   |  0


  Page 1 of 1

1

 
Topic: DEVELOP > C
User: "Sheldon Simms"
Date: 13 Nov 2003 01:26:48 PM
Object: components of a floating point value
I would like to portably extract the components of a floating point value:
sign, exponent, and significand. Based on the C floating point model
described in 5.2.4.2.2, I came up with the following code. There are
a couple of things to note about this code.
1) I convert the significand to an integer value in which the least
significant bit(s) of the integer correspond/s to the least significant
digit of the significand. This means that only as many low-order bits as
needed to encode DBL_MANT_DIG digits of the floating point radix are
significant in the integer value.
2) I assume that an unsigned long long int is large enough to represent
the significand. If this isn't true, the integer value used to represent
the significand will silently overflow.
I am interested in comments relating to the correctness/portability of the
code, pitfalls of the approach, tips on better/easier methods, etc.
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static void extract_double_components (double s)
{
int sign;
double tmp;
tmp = copysign(1.0, s);
sign = +1;
if (tmp < 0.0) sign = -1;
if (isinf(s))
{
if (sign < 0)
printf("-Infinity\n");
else
printf("+Infinity\n");
}
else if (isnan(s))
{
printf("NaN\n");
}
else if (s == 0.0)
{
if (sign < 0)
printf("-0.0\n");
else
printf("+0.0\n");
}
else
{
unsigned idx;
long exponent;
unsigned long long significand;
tmp = fabs(s);
/* find the exponent */
exponent = 0;
if (tmp < 1.0)
{
while (tmp < 1.0)
{
tmp = tmp * FLT_RADIX;
--exponent;
}
}
else
{
while (tmp >= 1.0)
{
tmp = tmp / FLT_RADIX;
++exponent;
}
tmp = tmp * FLT_RADIX; /* return to the range 1..2 */
}
/* find the significand */
significand = 0;
for (idx = 0; idx < DBL_MANT_DIG; ++idx)
{
significand = significand * FLT_RADIX;
tmp = tmp * FLT_RADIX;
if (tmp >= FLT_RADIX)
{
++significand;
tmp = tmp - FLT_RADIX;
}
}
printf("sign:%c significand:%llx exponent:%ld\n",
sign > 0 ? '+' : '-', significand, exponent);
}
}
int main (int argc, char *argv[])
{
double d;
if (argc != 2) { printf("usage: %s <double>\n", argv[0]); return -1; }
d = strtod(argv[1], NULL);
extract_double_components(d);
return 0;
}
A few test runs:
[sheldon@wsxyz mcc]$ ./a.out -Inf
-Infinity
[sheldon@wsxyz mcc]$ ./a.out 3.0
sign:+ significand:18000000000000 exponent:2
[sheldon@wsxyz mcc]$ ./a.out 1.5
sign:+ significand:18000000000000 exponent:1
[sheldon@wsxyz mcc]$ ./a.out 0.75
sign:+ significand:18000000000000 exponent:-1
[sheldon@wsxyz mcc]$ ./a.out 3.141592654
sign:+ significand:1921fb54524550 exponent:2
[sheldon@wsxyz mcc]$ ./a.out 2e-320
sign:+ significand:1fa00000000000 exponent:-1063
[sheldon@wsxyz mcc]$ ./a.out 2e-322
sign:+ significand:14000000000000 exponent:-1069
[sheldon@wsxyz mcc]$ ./a.out 2e-324
+0.0
[sheldon@wsxyz mcc]$ ./a.out -0.0
-0.0
.

User: "Glen Herrmannsfeldt"

Title: Re: components of a floating point value 13 Nov 2003 02:40:57 PM
"Sheldon Simms" <sheldonsimms@yahoo.com> wrote in message
news:pan.2003.11.13.19.26.47.903113@yahoo.com...


I would like to portably extract the components of a floating point value:
sign, exponent, and significand. Based on the C floating point model
described in 5.2.4.2.2, I came up with the following code. There are
a couple of things to note about this code.

1) I convert the significand to an integer value in which the least
significant bit(s) of the integer correspond/s to the least significant
digit of the significand. This means that only as many low-order bits as
needed to encode DBL_MANT_DIG digits of the floating point radix are
significant in the integer value.

2) I assume that an unsigned long long int is large enough to represent
the significand. If this isn't true, the integer value used to represent
the significand will silently overflow.

(snip)
There are machines with 128 bit floating point representations, with
something like 112 bits for mantissa.
You might consider whether your code works correctly for FLT_RADIX of 10 or
16. There is work on a standard for FLT_RADIX of 10, though with a slightly
more compact storage format than BCD. IBM has been making machines with
FLT_RADIX of 16 for almost 40 years now.
-- glen
.
User: "Sheldon Simms"

Title: Re: components of a floating point value 13 Nov 2003 03:24:26 PM
On Thu, 13 Nov 2003 20:40:57 +0000, Glen Herrmannsfeldt wrote:


"Sheldon Simms" <sheldonsimms@yahoo.com> wrote in message
news:pan.2003.11.13.19.26.47.903113@yahoo.com...


2) I assume that an unsigned long long int is large enough to represent
the significand. If this isn't true, the integer value used to represent
the significand will silently overflow.


(snip)

There are machines with 128 bit floating point representations, with
something like 112 bits for mantissa.

I'm aware of this. That's why I mentioned that the code makes the
assumption that it does.

You might consider whether your code works correctly for FLT_RADIX of 10 or
16. There is work on a standard for FLT_RADIX of 10, though with a slightly
more compact storage format than BCD. IBM has been making machines with
FLT_RADIX of 16 for almost 40 years now.

I have tried to make it radix neutral by using the value FLT_RADIX
everywhere it makes sense (except in a comment, I just noticed). Do
you see a problem with the code?
.



  Page 1 of 1

1

 


Related Articles
 

NEWER

pg.716     pg.544     pg.412     pg.311     pg.234     pg.175     pg.130     pg.96     pg.70     pg.50     pg.35     pg.24     pg.16     pg.10     pg.6     pg.3     pg.1

OLDER