2013-01-19 94 views
8

我想在纯的Lua的函数,其产生分数(23比特),一个指数(8位),和一个符号(1位),以便该数字大约等于math.ldexp(fraction, exponent - 127) * (sign == 1 and -1 or 1),然后将生成的值打包为32位。的Lua - 包装IEEE754单精度浮点数

在数学库中的某些功能引起了我的注意:

的frexp功能浮点值分解(V)到尾数(M)和指数(n),使得m的绝对值大于或等于0.5且小于1.0,并且v = m * 2^n。

请注意,math.ldexp是逆操作。

但是,我想不出有什么办法可以正确打包非整数。由于这个函数返回的尾数不是整数,我不确定我是否可以使用它。

是否有任何有效的方法来做类似math.frexp()的事情,它会返回一个整数作为尾数?或者,有没有更好的方法在Lua中以IEEE754单精度浮点格式打包数字?

预先感谢您。

编辑

我在此呈现的予制的功能的(希望)最终版本:

function PackIEEE754(number) 
    if number == 0 then 
     return string.char(0x00, 0x00, 0x00, 0x00) 
    elseif number ~= number then 
     return string.char(0xFF, 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, 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的格式。

我感谢你们的宝贵意见。

回答

7

将您从math.frexp()获得的有效数乘以2^24,并从指数中减去24以进行补偿。现在有效数是一个整数。请注意,有效位是位,而不是23位(您需要考虑IEEE-754编码中的隐含位)。

4

你见过this

我认为它以您想要的方式轻松简单。

+0

谢谢,我刚刚检查过它。它使用的方法与我的方法非常相似,但使用更清晰的格式。然而,它有一些问题(它似乎不支持零或非常小的数字),所以我正在基于它自己创建版本。完成后我会更新我的帖子。 – RPFeltz