我想在纯Lua中创建一个函数,它从一个数字生成一个分数(23位),一个指数(8位)和一个符号(1位),这样该数字大约等于math.ldexp(fraction,exponent – 127)*(sign == 1和-1或1),然后将生成的值打包成32位.
数学库中的某个功能引起了我的注意:
The frexp function breaks down the floating-point value (v) into a mantissa (m) and an exponent (n),such that the absolute value of m is greater than or equal to 0.5 and less than 1.0,and v = m * 2^n.
Note that math.ldexp is the inverse operation.
但是,我想不出任何正确打包非整数的方法.由于此函数返回的尾数不是整数,我不确定是否可以使用它.
有没有什么有效的方法来做类似于math.frexp()的东西,它返回一个整数作为尾数?或者是否有更好的方法在Lua中以IEEE754单精度浮点格式打包数字?
先谢谢你.
编辑
我在此提出我所做的函数的最终版本(希望):
function PackIEEE754(number) if number == 0 then return string.char(0x00,0x00,0x00) elseif number ~= number then return string.char(0xFF,0xFF,0xFF) else local sign = 0x00 if number < 0 then sign = 0x80 number = -number end local mantissa,exponent = math.frexp(number) exponent = exponent + 0x7F if exponent <= 0 then mantissa = math.ldexp(mantissa,exponent - 1) exponent = 0 elseif exponent > 0 then if exponent >= 0xFF then return string.char(sign + 0x7F,0x80,0x00) elseif exponent == 1 then exponent = 0 else mantissa = mantissa * 2 - 1 exponent = exponent - 1 end end mantissa = math.floor(math.ldexp(mantissa,23) + 0.5) return string.char( sign + math.floor(exponent / 2),(exponent % 2) * 0x80 + math.floor(mantissa / 0x10000),math.floor(mantissa / 0x100) % 0x100,mantissa % 0x100) end end function UnpackIEEE754(packed) local b1,b2,b3,b4 = string.byte(packed,1,4) local exponent = (b1 % 0x80) * 0x02 + math.floor(b2 / 0x80) local mantissa = math.ldexp(((b2 % 0x80) * 0x100 + b3) * 0x100 + b4,-23) if exponent == 0xFF then if mantissa > 0 then return 0 / 0 else mantissa = math.huge exponent = 0x7F end elseif exponent > 0 then mantissa = mantissa + 1 else exponent = exponent + 1 end if b1 >= 0x80 then mantissa = -mantissa end return math.ldexp(mantissa,exponent - 0x7F) end
我改进了利用隐含位的方法,并为特殊值(如NaN和无穷大)添加了适当的支持.我的格式基于catwell链接到的脚本.
我感谢你们的好建议.
解决方法
将您从math.frexp()得到的有效数乘以2 ^ 24,并从指数中减去24进行补偿.现在有效数是一个整数.请注意,有效位数是24位,而不是23位(您需要考虑IEEE-754编码中的隐含位).