# float from reordered bytes

Context: communicating with programmable logic controllers using Modbus or derivatives of Modbus protocol. When float data is stored on these devices the byte ordering is not prescribed, and seemingly every possible variant is used by different manufacturers. Having reassembled 4 bytes into the 'correct' order, how should one turn those bytes into a variable? I found two solutions, each of them a bit of a kluge. If you know a better way to do this, please show me how!

first solution was to write the bytes to a binary file and read them as float (the snippet here does the reverse, but you get my drift)
function float2bytes(var)
variable var
make /O/B/U/n=4 w_bytes
variable refnum
open /Z=1/P=home refNum as "ieee.bin"
fbinwrite /F=4 refnum, var
FSetPos refnum, 0
close refnum
end

And a programmatic solution:

// get number value of binary32 stored as 4 bytes in an 8 bit unsigned integer wave
function IEEE(w_bytes)
wave w_bytes // four bytes
// bytes should be ordered low word first, low byte first
// i.e. first byte LSB is bit 0 and 4th byte MSB is bit 31 of IEEE 754 single-precision binary floating-point format.

make /free/b/u/n=32 w_binary // seems wasteful, but keeps things organised
w_binary=(w_bytes[3-floor(p/8)]&2^(7-mod(p,8)))>0

// the 32 points of w_binary now contain contain the 32 bits of an IEEE float, starting from bit 32 (the sign bit)

variable v_sign, v_exponent, v_fraction, i

v_sign=w_binary[0]
// next 8 bits hold the exponent
v_exponent=0
for (i=0; i<8; i+=1)
v_exponent+=w_binary[8-i]*2^i
endfor
// last 23 bits hold the fraction
v_fraction=1
for (i=0; i<23; i+=1)
v_fraction+=w_binary[9+i]*2^-(i+1)
endfor

if (v_exponent==0)
if (v_fraction>1)
return (-1)^v_sign*(v_fraction-1)*2^-126
else
return (-1)^v_sign*0
endif
elseif(v_exponent==0xFF)
return nan
endif

return (-1)^v_sign*v_fraction*2^(v_exponent-127)
end
I learned from Howard Rodstein's follow up to a question on the mailing list that Redimension /E=1 provides a much more straightforward way to do this.

It's the /E flag that I was missing: "Force reshape without converting or moving data."

Forum

Support

Gallery