IEEE-754 Floating Point Converter

#1

Hello, I am using Node-RED to convert convert IEEE-754 Floating Point to decimal.
I am using this code to convert the values wich I get the right positive values but I obtain -Infinity for the negative values.

Code:
var buf = Buffer.from(msg.payload);
var sign = buf.readFloatBE() >> 31 === 0 ? 1 : -1 ;
var exponent = (buf.readFloatBE() & 0b01111111100000000000000000000000);
var significand = (buf.readFloatBE() & ~(-1 << 23));
msg.payload = sign * significand * Math.pow(2, exponent);
return msg;

Can you please help me to get the negative values.

0 Likes

#2

That exponent calc doesn't look right, it will give you a huge number if the exponent is non-zero. I would have expected to see it shifted right.
Are you sure you get the right values for +ve numbers? Have you tried with a big +ve?
Where did you get the code?

0 Likes

#3

Yes, I get the right +ve values. I didn't tried with a big +ve values ( The maximum value that I converted it is about 4000).

0 Likes

#4

Where did you get that code? It is not right.

0 Likes

#5

Or if you did not copy some code where is the algorithm you are trying to replicate?

0 Likes

#6

I have tried several code after I changed them to get the value that I had . Can you help me please ?

0 Likes

#7

I am not going to start working out the algorithm to do the conversion. If you google and find the algorithm to use (which presumably you have already in order to get nearly there) then I can help you code it in javascript.

0 Likes

#8

I found this code but I didn't get the right Values

function Bytes2Float32(bytes) {
    var sign = (bytes & 0x80000000) ? -1 : 1;
    var exponent = ((bytes >> 23) & 0xFF) - 127;
    var significand = (bytes & ~(-1 << 23));

    if (exponent == 128) 
        return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);

    if (exponent == -127) {
        if (significand == 0) return sign * 0.0;
        exponent = -126;
        significand /= (1 << 22);
    } else significand = (significand | (1 << 23)) / (1 << 23);

    return sign * significand * Math.pow(2, exponent);
}
0 Likes

#9

That looks more likely to be correct. Have you got some sample values and what they should convert to?

0 Likes

#10

That function works for me with examples from https://en.wikipedia.org/wiki/Single-precision_floating-point_format

[{"id":"f64c029.2c5838","type":"function","z":"2ae8b25a.bffaa6","name":"Bytes to float","func":"let bytes = Number(msg.payload);\nmsg.payload = Bytes2Float32(bytes)\nreturn msg;\n\nfunction Bytes2Float32(bytes) {\n    var sign = (bytes & 0x80000000) ? -1 : 1;\n    var exponent = ((bytes >> 23) & 0xFF) - 127;\n    var significand = (bytes & ~(-1 << 23));\n\n    if (exponent == 128) \n        return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);\n\n    if (exponent == -127) {\n        if (significand === 0) return sign * 0.0;\n        exponent = -126;\n        significand /= (1 << 22);\n    } else significand = (significand | (1 << 23)) / (1 << 23);\n\n    return sign * significand * Math.pow(2, exponent);\n}","outputs":1,"noerr":0,"x":310,"y":612,"wires":[["6e888b6a.40c874"]]},{"id":"6e888b6a.40c874","type":"debug","z":"2ae8b25a.bffaa6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":502,"y":612,"wires":[]},{"id":"2dc3b0d4.06517","type":"inject","z":"2ae8b25a.bffaa6","name":"1","topic":"","payload":"0x3f800000","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":89,"y":614,"wires":[["f64c029.2c5838"]]},{"id":"43e54f8e.0cf598","type":"inject","z":"2ae8b25a.bffaa6","name":"-2","topic":"","payload":"0xc0000000","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":84,"y":650,"wires":[["f64c029.2c5838"]]},{"id":"a8fc7865.b2a438","type":"inject","z":"2ae8b25a.bffaa6","name":"Pi","topic":"","payload":"0x40490fdb","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":82,"y":684,"wires":[["f64c029.2c5838"]]}]
0 Likes

#11

Thank you very much @Colin.
But I have just one question to ask. befor the function node I have a node which I obtain a buffer like this [67,76,0,0]. I have to change Number to buffer? like this :
let bytes = buffer.from(msg.payload);
msg.payload = Bytes2Float32(bytes)
return msg;
I changed it but I get always 0.

0 Likes

#12

It is important to be careful in your choice of words. You say you have a buffer like [67,67,0,0] but then say you want to use buffer.from on it. If it is already a buffer then why do buffer.from? I suspect you mean that it is an array. If so then there is no need to convert it to a buffer. If the array is in msg.payload you can do

let bytes = (((((msg.payload[0] << 8) + msg.payload[1]) << 8) + msg.payload[2]) << 8) + msg.payload[3]
msg.payload = Bytes2Float32(bytes)
return msg;
1 Like

#13

The wikipedia post has an error. Not in the conversion but 3.1415927410 is not pi!

[Edit] No it isn't, that is as close as you can get in single precision float.

0 Likes

#14

As this has come up before I have added a flow to flows library with the function to do this conversion.

https://flows.nodered.org/flow/359ead34237b7ab6ec0465ee85a34b62

2 Likes

#15

Thank you very much @Colin.

0 Likes