[comp.lang.c] double-precision dissection

bson@rice-chex.ai.mit.edu (Jan Brittenson) (12/01/90)

   I'm looking for a fairly portable way of extracting the exponent of
a double, such that:


	(int) EXP_OF(1.2345e-17) == -17


   Portability is more important than speed. Precision isn't of
importance either, as the mantissa is handled separately. I'm using
SunOS 4.1, and didn't find any clues at all as to how to accomplish
this in the man pages. (I.e. no functions for dissecting doubles.) Use
of pure <math.h>-declared functions/defined would be perfect.

   I guess one way would be to set the mantissa to 1 and return the
log10.


   My aim is to generate 10's complement BCD-coded floating-point data
in a cross assembler where ease of porting is the main objective.
Doubles don't conform to the range of the BCD numbers, but that's not
a big issue. For simplicity all floating-arithmetic is done in
doubles, and are converted to BCD numbers only when generating data.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (12/03/90)

In article <12131@life.ai.mit.edu>, bson@rice-chex.ai.mit.edu (Jan Brittenson) writes:
>    I'm looking for a fairly portable way of extracting the exponent of
> a double, such that:
> 	(int) EXP_OF(1.2345e-17) == -17
> 
> I'm using SunOS 4.1, and didn't find any clues at all as to how to accomplish
> this in the man pages. (I.e. no functions for dissecting doubles.) Use
> of pure <math.h>-declared functions/defined would be perfect.

I can tell from this that you didn't look at
	man floating_to_decimal
which covers
	single_to_decimal(),
	double_to_decimal(),
	extended_to_decimal().
Those functions are not portable, but if you don't mind an #if in your
program it would be silly not to avail yourself of correct rounding when
you can get it.

Also in the SunOS 4.1 manual pages is the ANSI C function frexp():

	double frexp(double x, int *pexp)

which returns y and sets *pexp such that y*2**(*pexp) == x
and y .in. [1/2,1) or x == y == 0 which counts as "dissecting" a double
in my book.

The very simplest dodge is to exploit the fact that you apparently want
a decimal exponent.  Very well, what's wrong with sprintf()?

	#include <float.h>
	/* defines DBL_DIG */
	#include <stdio.h>
	/* defines sprintf() */
	#include <stdlib.h>
	/* defines atoi() */

	int decimal_exponent(double x)
	    {
		char buffer[sizeof "+1.E-99999" + DBL_DIG];

		(void) sprintf(buffer, "%+.*e", DBL_DIG, x);
		return atoi(buffer + 3 + DBL_DIG);
	    }

Beware:  I haven't tested that.
-- 
I am not now and never have been a member of Mensa.		-- Ariadne.