voglio fare una funzione in puro Lua che genera un frazione (23 bit), un esponente (8 bit), e un segno(1 bit) da un numero, in modo che il numero sia approssimativamente uguale a math.ldexp(fraction, exponent - 127) * (sign == 1 and -1 or 1)
e quindi comprime i valori generati in 32 bit.Lua - imballaggio numeri a virgola mobile in singola precisione IEEE754
una certa funzione nella libreria matematica attirato la mia attenzione:
La funzione frexp rompe il valore in virgola mobile (v) in una mantissa (m) e un esponente (n), in modo tale che il il valore assoluto di m è maggiore o uguale a 0.5 e minore di 1.0 e v = m * 2^n.
Si noti che math.ldexp è l'operazione inversa.
Tuttavia, non riesco a pensare ad alcun modo per comprimere correttamente i numeri non interi. Poiché la mantissa restituita da questa funzione non è un numero intero, non sono sicuro di poterla usare.
Esiste un modo efficace per fare qualcosa di simile a math.frexp()
che restituisce un intero come mantissa? O c'è forse un modo migliore per impacchettare i numeri nel formato a virgola mobile IEEE754 a precisione singola in Lua?
Grazie in anticipo.
Modifica
presento la (si spera) versione definitiva delle funzioni che ho fatto:
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
ho migliorato il modo di utilizzare il bit implicita e aggiunto il supporto adeguato per valori speciali tali come NaN e infinito. Ho basato la formattazione su quella della sceneggiatura di catwell collegata a.
Grazie per l'ottimo consiglio.
Grazie, l'ho appena controllato. Il metodo che usa è molto simile a quello del mio, ma usa una formattazione più pulita. Tuttavia, ci sono alcuni problemi con esso (non sembra supportare zero o numeri molto piccoli), quindi sto facendo la mia versione basata su di esso. Aggiornerò il mio post quando è fatto. – RPFeltz