Binary to Float?

Hi,

Is there a way to easily convert binary to 32 bit IEEE float in Arduino Due?

Like for a 16 bit int, I can do something like:

num = B1 << 8 + B0;

For the float, tried something like:

float num = B01000001<<32 + B00101010<<16 + B00000000<<8 + B00000000;

But I get 0 as return instead of 10.625, thx!

Delta_G:
Cast your binary constants to long so they don't shift off the end. And the first shift should be 24 no?

float num = (long)B01000001<<24 + (long)B00101010<<16 + B00000000<<8 + B00000000;

Oops, yeah, it supposed to be 24.
But I tried that, doesn't seems to work, I still get 0.00

I tried casting it like:

float num = (long)(B01000001<<24) + (long)(B00101010<<16) + B00000000<<8 + B00000000;

but then I get 704643072.00 as then result...

[EDIT]

Finally found a site which solved this already.
https://answers.yahoo.com/question/index?qid=20090809235330AAfcN0T

I wrote this into a method for easier reuse.

void setup() {
  Serial.begin(115200);
}

void loop() {  
  float num = binToFloat( B01000001, B00101010, B00000000, B00000000);
  Serial.println(num);
  delay(2000);
}

float binToFloat(byte D3, byte D2, byte D1, byte D0)
{
  byte bin[4];
  
  bin[3] = D3;
  bin[2] = D2;
  bin[1] = D1;
  bin[0] = D0;
  
  return *( (float*) bin ); 
}

The correct choice is to use memcpy...
https://www.google.com/search?q=c+binary+to+float+punning+memcpy

The question is often asked. So often that...
https://www.google.com/search?q=union+float+site%3Aforum.arduino.cc
...the first hit looks promising.

sorry, I googled the wrong keywords earlier...
https://www.google.com/search?q=binary+to+float

All you have to do is a simple cast:

long inval = 123456;
float floatval = (float)inval;

Regards,
Ray L.

Billwaa:
sorry, I googled the wrong keywords earlier...

No need to apologize. Just trying to teach you to fish.

Billwaa:
Oops, yeah, it supposed to be 24.
But I tried that, doesn't seems to work, I still get 0.00

Oh... I thought you were trying to take ASCII strings of binary (like "01100011") and get it to return "0x63".

What's the purpose of taking binary numbers and converting several into one value?

I'm curious what that would be used for.

Wouldn't it be easier to specify the whole binary number in one shot, something like this:

** **float value = 0b100001101010001110000110101000111000011010100011;** **

..or am I not getting what you're after?

Are you trying to receive an integer value to a float, or are you receiving the four bytes of a float variable, and trying to re-assemble them into a valid float value? Those are two completely different scenarios.

Regards,
Ray L.

Re-assemble (unpacking).

The bit pattern is for 10.63 not 24.

Post #2 was modified while I composed my post which has created confusion.

Another potential solution...

typedef union
{
  uint8_t  b[4];
  float    f;
}
packed_t;

void setup( void )
{
  Serial.begin( 115200 );

  packed_t p;

  p.b[0] = B00000000;
  p.b[1] = B00000000;
  p.b[2] = B00101010;
  p.b[3] = B01000001;
  
  Serial.println( p.f );
  
  p.f = 24.0;
  
  Serial.print( p.b[0], BIN );
  Serial.write( '\t' );
  Serial.print( p.b[1], BIN );
  Serial.write( '\t' );
  Serial.print( p.b[2], BIN );
  Serial.write( '\t' );
  Serial.print( p.b[3], BIN );
  Serial.println();
}

void loop( void ) { }

If that is correct, then your solution with the union is the correct way to do it.

Regards,
Ray L.

Naw. Any packing / unpacking technique has risks and benefits. Even binToFloat from post #2 has merit.

The c language include unions, in part, to provide a "clean" way to deal with this kind of issue. A union is the cleanest, safest way of handling the conversion (but it is still far from foolproof). The other method, using just a type cast, is quite unsafe, and will likely not work reliably. It may work on an AVR processor, but it certainly will not on some other processors. Try it on a Due, and I think you'll find it works sometimes, and not other. They union method will work on any processor.

I don't know what the internals of binToFloat look like, but I'd bet it uses a union.

Regards,
Ray L.

I don't know what the internals of binToFloat look like, but I'd bet it uses a union.

Oh dear. Looks like you get an F for reading comprehension.

RayLivingston:
The other method, using just a type cast... Try it on a Due, and I think you'll find it works sometimes, and not other.

Give it a spin. Let us know what happens...

void setup() 
{
  uint32_t t;
  
  t = (uint32_t)B01000001<<24 | (uint32_t)B00101010<<16 | (uint32_t)B00000000<<8 | (uint32_t)B00000000;
  
  float n = *(float*)&t;
  
  Serial.begin( 115200 );
  
  Serial.println( n );
}

void loop() { }

http://xyproblem.info/ springs to mind.

RayLivingston:
If that is correct, then your solution with the union is the correct way to do it.

Regards,
Ray L.

Here's an actual example where I convert data (a generated waveform) into an output stream based on whether it's 8 bit, 16 bit, 32 bit or float using a union:

    union { // wav data access as float, uint32 and individual bytes
        uint8_t b[sizeof (float)]; // individual bytes
        uint32_t i; // "input" as an int
        float f; // "input" as a float
    } data;

//.................

    if (format == 1) {
        data.i = accum; // put data in as integer

    } else {
        data.f = accum; // put data in as float
    }

    for (z = 0; z < channels; z++) {
        for (y = 0; y < numbytes; y++) {
            *outptr++ = data.b[y]; // write each byte to the buffer
        }
    }