Hi!
The algorithms I've seen on the net require quite some bit hacking to
get that done. Like:
https://kyledewey.github.io/comp122-fall17/lecture/week_2/floating_point_interconversions.html
I've designed the following algorithm which seems more straight forward.
Now my question is: is this a reinvention of a known one -- or is this a
new approach? Note that this works best with a large mantissa -- so I
provided a word to normalize the mantissa/exponent pair, called
normalize10().
Also included: an integer version of pow(). BTW, no idea why it works,
but it works for sane input values.
Hans Bezemer
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <limits.h>
typedef struct {
long long mantissa;
long exponent;
} me;
long power (long base, long exp) /* integer version of pow() */
{
long long a = 1LL;
do {
if (exp & 1) a *= base;
exp /= 2; base *= base;
} while (exp != 0);
return (a);
}
/* normalize mantissa/exponent */
void normalize10 (me* zen, long long mant, long exp)
{ /* save sign of mantissa */
char msign = (zen -> mantissa) < 0LL;
/* get absolute value of mantissa */
zen -> mantissa = llabs (zen -> mantissa);
/* increase mantissa */
while ((zen -> mantissa < mant) && (zen -> exponent > exp))
{ /* while between limits */
zen -> mantissa *= 10; --(zen -> exponent);
} /* multiply by 10 */
/* correct mantissa sign if
required */
if (msign) zen -> mantissa = -(zen -> mantissa);
}
/* convert from radix 10 to
radix 2 */
void me10tome2 (me* zen)
{ /* save signs of mantissa and
exponent */
char msign = (zen -> mantissa) < 0LL;
char esign = (zen -> exponent) < 0L;
long exp2;
long me10; /* radix 10 multiplication factor */
long me2; /* radix 2 multiplication factor */
if (zen -> exponent) { /* if exponent is non-zero */
zen -> mantissa = llabs (zen -> mantissa);
zen -> exponent = labs (zen -> exponent);
/* get absolute value of
mantissa and exponent */
exp2 = (((zen -> exponent) * 10) + 2) / 3;
/* convert exponent to radix 2 */
me10 = power (10, zen -> exponent);
me2 = 1 << exp2; /* calculate multiplication
factors */
if (esign) { /* if negative exponent */
zen -> exponent = -exp2;
zen -> mantissa = (zen -> mantissa * me2) / me10;
} else { /* if positive exponent */
zen -> exponent = exp2;
zen -> mantissa = (zen -> mantissa * me10) / me2;
}
/* correct mantissa sign if
required */
if (msign) zen -> mantissa = -(zen -> mantissa);
}
}
int main (int argc, char** argv)
{
me z = { 1000LL, -4L }; /* 1000E-4 */
normalize10 (&z, LONG_MAX, -9); /* normalize mantissa and
exponent */
me10tome2 (&z); /* convert to radix 2 */
/* check result */
printf("Verification:\t%lld * 2^(%ld) = %f\n",
z.mantissa, z.exponent, z.mantissa * pow(2.0, z.exponent));
}
--- PyGate Linux v1.5.16
* Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)