0
votes

I've looked around Stackoverflow for a few days trying to solve this problem and played in JsFiddle for a while but no luck so far.

Here's my problem: i receive a base64 encoded string which is packed with several values. Both Unsigned Integers and floating point numbers. The decoding of the base64 to a hex string goes fine. So do the unsigned integers. The problem lies in decoding the floats.

b76a40e9000000350a3d422d00000059e37c409a0000002f90003b6e00000000

This is my data, as an example well use the first 32 bits, is a IEE-754 float with byte order 1-0-3-2. So that's 0xb76a40e9 which i know is 7.30363941192626953125 and when we swap it to be 3-2-0-1 it becomes 0x40e9b76a. When i put this hex string into https://www.h-schmidt.net/FloatConverter/IEEE754.html that is confirmed.

My question is, and iv'e searched for this very long, if there is an implementation in javascript that converts hexadecimal IEEE-754 float strings into a javascript float. JS' own parseInt will accept hex, but parseFloat doesn't for some reason?

Any imput would be greatly appreciated, all the examples of code people made thusfar result in different numbers than i'm expecting.

1
Could you explain me what is byte order? - Carr
@Carr this image should explain imgur.com/gf3pBwql.png It's mainly a way for the device that i receive this data from to send it over a bus. Maybe not very relevant for the question. - broodrooster
And 0xb76a40e9 which i know is 7.303 ? Under my test by 0xb76a40e9.toString(10) the output is 3077193961 in decimal, how you get 7.303? - Carr
@Carr you would have to swap byte order first, so 0x40e9b76a.toString(10) should result in something like 7.30363941192626953125 - broodrooster
Rounding off to 7.303 makes this question unclear: Do you actually mean 7.3036394119262695? - Josh Lee

1 Answers

7
votes

Unpacking a float from a word using DataView:

> v = new DataView(new ArrayBuffer(4))
> v.setUint32(0, 0x40e9b76a)
> v.getFloat32(0)
7.3036394119262695

(Recommended over Uint32Array and Float32Array because it does not inherit the platform's endianness.)

You could also use this to swap the two 16-bit units:

> v.setUint32(0, 0xb76a40e9)
> ((hi, lo) => {
    v.setUint16(0, hi);
    v.setUint16(2, lo);
  })(v.getUint16(2), v.getUint16(0))
> v.getUint32(0).toString(16)
'40e9b76a'