我想在純的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的格式。
我感謝你們的寶貴意見。
謝謝,我剛剛檢查過它。它使用的方法與我的方法非常相似,但使用更清晰的格式。然而,它有一些問題(它似乎不支持零或非常小的數字),所以我正在基於它自己創建版本。完成後我會更新我的帖子。 – RPFeltz