Convert byte array to float in Lua [Float Data Structure]
I have the ability to read the memory with Lua, but I've run into a problem. I want to read a float value.
I have, what I presume to be a float, in the 开发者_如何转开发memory which looks like this.
Byte Array 65 B6 40 43 EC 35 87 41 51 04 9E 3F
Float Value 192.712478637695
I know the float value because I'm using a memory editor. In Lua I have a function similar to memcpy, it's called readmem(Address,bytes) it returns an integer value.
How would I read the byte array into a float in Lua using readmem.
For the sake of this question I suppose you could assume that the 6 in 65 is address 00000000.
Weird, this seems to be stored in middle-endian order. (I checked this with http://www.h-schmidt.net/FloatApplet/IEEE754.html)
Anyway, you can do the conversion in pure Lua using code from http://yueliang.luaforge.net/
See also http://lua-users.org/lists/lua-l/2010-03/msg00910.html
If you can use C, try one of the libraries listed in http://lua-users.org/wiki/StructurePacking
This is a fair amount of work to get everything right.
You'll need to extract the exponent and significand (the significand is sometimes called the mantissa), convert to float using math.frexp
, and then negate the result if the sign bit is set. You'll also have to recognize denormalized numbers and NaNs. (In a normalized number, the most significant bit of the significand is implicit; in a denormalized number it's explicit.)
If you simply must do this yourself, you'll find it helpful to read Dave Goldberg's article on everything a computer scientist needs to know about floating point.
Also keep in mind that a Lua number is an IEEE double, and be careful about precision.
If I were doing this myself, there's no way I'd go through all this pain—instead I'd write C code to read the bytes and call lua_pushnumber
.
string.pack
Passing 'f'
as the first parameter will return a 4 byte string of the single precision representation, while 'd'
will return an 8 byte string of the double precision representation. You can even declare the endianness of the float
You must write a C function to accomplish the conversion. Lua does not have casts or anything like them.
I cleaned up the answer from @lhf a little:
function BinToFloat32(bin)
local sig = bin:byte(3) % 0x80 * 0x10000 + bin:byte(2) * 0x100 + bin:byte(1)
local exp = bin:byte(4) % 0x80 * 2 + math.floor(bin:byte(3) / 0x80) - 0x7F
if exp == 0x7F then return 0 end
return math.ldexp(math.ldexp(sig, -23) + 1, exp) * (bin:byte(4) < 0x80 and 1 or -1)
end
I can confirm that this works perfectly for little endian byte input.
精彩评论