2013-01-19 132 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