Chan Kim Chan Kim - 1 month ago 7
C Question

Returning unsigned int bits values as float (solved)

In the below code, I have

bits
correct (it was originally
bits<float>
type in C++ program, but I just used
uint32
in this C program.). I want to use the bits as the ieee754
float
value. Assigning just
float_var = int_val
won't do it because it interprets the value and casts to
float
. I want to just use the bit values as floating point values.

uint32 bits = mantissa_table[offset_table[value>>10]+(value&0x3FF)] + exponent_table[value>>10];
ab_printf("bits = %x\n", bits);
float out;
//memcpy(&out, &bits, sizeof(float)); // original
char *outp = &out;
char *bitsp = &bits;
outp[0] = bitsp[0];
outp[1] = bitsp[1];
outp[2] = bitsp[2];
outp[3] = bitsp[3];
ab_printf("out = %x\n", out);
return out;


part of the program run result :

ff = 3.140000
hh = 4248
bits = 40490000
out = 40092000


There must be something basic I don't know.
For your information, above run is turning float
3.14
to half-precision and back to single precision and I printed the intermediate values.
0x4248
is in half-precision
3.140625
and bits
0x40490000
is in single-precision also
3.140625
, so I just need to return it as
float
.

ADD : After reading comments and answers, I did some experiment and found that the single-float value is seen correct inside the function(using type punning using pointer, or using union), but when it is returned to the calling function, it is not printed correctly. Then I changed something and now it works with most methods. I don't know what had been wrong.. Sorry. (The ldexp, ldexpf didn't work).

== half.h ==

typedef unsigned short uint16;
typedef unsigned short half;
extern uint16 float2half_impl(float value);
extern float half2float_impl(half value);


== test4.c ==

#include "half.h"

int main()
{
float vflt = 3.14;
half vhlf;
float vflt2;

ab_printf("vflt = %f\n", vflt);
vhlf = float2half_impl(vflt);
ab_printf("vhlf = %x\n", *(unsigned short *)&vhlf);
float vflt2 = half2float_impl(vhlf);
ab_printf("received : vflt2 = %f\n", vflt2);
}


== half.c ==

#include "half.h"
....
inline float half2float_impl(uint16 value)
{
//typedef bits<float>::type uint32;
typedef unsigned int uint32;
static const uint32 mantissa_table[2048] = {
....
uint32 bits = mantissa_table[offset_table[value>>10]+(value&0x3FF)] + exponent_table[value>>10];
ab_printf("bits = %x\n", bits);

float out;

#define METHOD 0 // 0, 2, 3 work. 1 and 4 not work
#if METHOD == 0
memcpy(&out, &bits, sizeof(float));
ab_printf("out = %f\n", *(float *)&out); // prints 3.140625
return out;
#elif METHOD == 1
#warning METHOD 1
ab_printf("bits = %f\n", *(float *)&bits); // prints 3.140625
return bits;
#elif METHOD == 2 // prints float ok but return value float prints wrong
#warning METHOD 2
union {
unsigned int ui;
float xx;
} aa;
aa.ui = bits;
ab_printf("xx = %f\n", aa.xx); // prints 3.140625
return aa.xx; // but return values prints wrong
#elif METHOD == 3 // prints float ok but return value float prints wrong
#warning METHOD 3
ab_printf("bits = %f\n", *(float *)&bits); // prints 3.140625
return *(float *)&bits; // but return values prints wrong
#elif METHOD == 4
#warning METHOD 4
out = toFloat(bits);
ab_printf("out = %f\n", out); // prints 3.140625
return out;
#else
#warning returning 0
return 0;
#endif
}


the result shows corret now.

== method 0 ==
vflt = 3.140000
vhlf = 4248
bits = 40490000
received : vflt2 = 3.140625

TRAP_error(t_NO: 0x80 ) PSR: 0x06401fc6, PC: 0x20001144

== method 1 ==
vflt = 3.140000
vhlf = 4248
bits = 40490000
bits = 3.140625
received : vflt2 = 1078525952.000000

TRAP_error(t_NO: 0x80 ) PSR: 0x06401fc6, PC: 0x20001144

== method 2 ==
vflt = 3.140000
vhlf = 4248
bits = 40490000
xx = 3.140625
received : vflt2 = 3.140625

TRAP_error(t_NO: 0x80 ) PSR: 0x06401fc6, PC: 0x20001144

== method 3 ==
vflt = 3.140000
vhlf = 4248
bits = 40490000
bits = 3.140625
received : vflt2 = 3.140625

TRAP_error(t_NO: 0x80 ) PSR: 0x06401fc6, PC: 0x20001144

== method 4 ==
vflt = 3.140000
vhlf = 4248
bits = 40490000

Answer Source

This:

out = *(float *)&bits;

Allows you to read bits as a float without any explicit or implicit conversion by using pointer magic.

Notice, however, that endinaness might get you a bit screwed doing this (just like memcpy() would too, so if it worked for you this method should work too, but keep in mind that this can change from architecture to architecture).