http://www.velocityreviews.com/forums/(EMail Removed) (Goran) wrote in
news:(EMail Removed) om:
> Hi!
>
> I need to convert from a unsigned char array to a float. I don't think
> i get the right results in the program below.
>
> unsigned char array1[4] = { 0xde, 0xc2, 0x44, 0x23}; //I'm not sure in
> what order the data is stored so i try both ways.
> unsigned char array2[4] = { 0x23, 0x44, 0xc2, 0xde};
>
> float *pfloat1, *pfloat2;
>
> pfloat1 = (float *)array1;
> pfloat2 = (float *)array2;
>
> printf("pfloat1 = %f, pfloat2 = %f\n", pfloat1, pfloat2);
As Artie pointed out, these need to be floats, not pointers
to floats. Also, pfloat1 and pfloat2 might not be correctly
aligned for a float.
> The result here is:
> pfloat1 = 0.000000, pfloat2 = 6999176012340658176.000000
But if you fix the above, then these look OK for IEEE
single precision, although you have a bogus amount of
precision for pfloat2, and not enough for pfloat1. If
you use %g you should see results something like
pfloat1 = 1.06664e17, pfloat2 = 6.99918e+18
> I know this data is stored in singleprecision floatingpoint number.
> Calculating this with the formula: 1.mantissa * 2^(exp127) gets the
> following results:
No it doesn't.
> 6614457784713468934.9861376 when using array1
> 79.784837 when using array2.
>
> Anyone know why i get so bad results?
I would suggest that you have made in mistake in your
calculations. Here is some code that does it for you:
$ type ieee2float.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <assert.h>
double decode_ieee_single(const void *v, int natural_order)
{
const unsigned char *data = v;
int s, e;
unsigned long src;
long f;
double value;
if (natural_order) {
src = ((unsigned long)data[0] << 24) 
((unsigned long)data[1] << 16) 
((unsigned long)data[2] <<

((unsigned long)data[3]);
}
else {
src = ((unsigned long)data[3] << 24) 
((unsigned long)data[2] << 16) 
((unsigned long)data[1] <<

((unsigned long)data[0]);
}
s = (src & 0x80000000UL) >> 31;
e = (src & 0x7F800000UL) >> 23;
f = (src & 0x007FFFFFUL);
if (e == 255 && f != 0) {
/* NaN (Not a Number) */
value = DBL_MAX;
}
else if (e == 255 && f == 0 && s == 1) {
/* Negative infinity */
value = DBL_MAX;
}
else if (e == 255 && f == 0 && s == 0) {
/* Positive infinity */
value = DBL_MAX;
}
else if (e > 0 && e < 255) {
/* Normal number */
f += 0x00800000UL;
if (s) f = f;
value = ldexp(f, e  150);
}
else if (e == 0 && f != 0) {
/* Denormal number */
if (s) f = f;
value = ldexp(f, 149);
}
else if (e == 0 && f == 0 && s == 1) {
/* Negative zero */
value = 0;
}
else if (e == 0 && f == 0 && s == 0) {
/* Positive zero */
value = 0;
}
else {
/* Never happens */
printf("s = %d, e = %d, f = %lu\n", s, e, f);
assert(!"Woops, unhandled case in decode_ieee_single()");
}
return value;
}
int main(void)
{
unsigned char f[4] = {0xde, 0xc2, 0x44, 0x23};
printf("0x%02X%02X%02X%02X as an IEEE float is %f\n",
f[0], f[1], f[2], f[3], decode_ieee_single(f, 0));
printf("0x%02X%02X%02X%02X as an IEEE float is %f\n",
f[3], f[2], f[1], f[0], decode_ieee_single(f, 1));
return 0;
}
$ cc ieee2float
$ link ieee2float
$ run ieee2float
0xDEC24423 as an IEEE float is 0.000000
0x2344C2DE as an IEEE float is 6999176012340658200.000000
This code has not been exhastively tested. The above output
was generated on system not using IEEE floating point, but its
output agrees with your IEEE system.
Phil T