I eine Funktion in reiner Lua machen möge, die ein Fraktion (23 Bits) erzeugt, einen Exponenten (8 Bits) und ein Zeichen (1 Bit) von einer Zahl, so dass die Zahl ungefähr gleich math.ldexp(fraction, exponent - 127) * (sign == 1 and -1 or 1)
ist, und packt dann die generierten Werte in 32 Bits.Lua - Verpackungs IEEE754 einfache Genauigkeit Gleitkommazahlen
eine bestimmte Funktion in der Mathematik-Bibliothek meine Aufmerksamkeit erregte:
Die frexp Funktion bricht den Gleitkommawert (v) in eine Mantisse (m) und einen Exponenten (n), derart, dass die der absolute Wert von m ist größer als oder gleich 0,5 und kleiner als 1,0 und v = m * 2^n.
Beachten Sie, dass math.ldexp die umgekehrte Operation ist.
Allerdings kann ich mir keine Möglichkeit vorstellen, nicht ganzzahlige Zahlen richtig zu packen. Da die von dieser Funktion zurückgegebene Mantisse keine ganze Zahl ist, bin ich mir nicht sicher, ob ich sie benutzen kann.
Gibt es eine effiziente Möglichkeit, etwas Ähnliches wie math.frexp()
zu tun, das eine ganze Zahl als Mantisse zurückgibt? Oder gibt es vielleicht eine bessere Möglichkeit, Zahlen in das IEEE754 Gleitkomma-Format mit einfacher Genauigkeit in Lua zu packen?
Vielen Dank im Voraus.
bearbeiten
stelle ich hiermit die (hoffentlich) letzte Version der Funktionen, die ich gemacht:
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
I verbessert die Art und Weise die implizite Bit zu nutzen und hinzugefügt richtige Unterstützung für spezielle Werte, als NaN und Unendlichkeit. Ich habe die Formatierung auf die des mit catwell verknüpften Skripts gestützt.
Ich danke Ihnen beiden für Ihren guten Rat.
Danke, ich habe es gerade überprüft. Die verwendete Methode ist der von mir sehr ähnlich, verwendet aber eine sauberere Formatierung. Es gibt jedoch ein paar Probleme damit (es scheint keine Null oder sehr kleine Zahlen zu unterstützen), also mache ich meine eigene Version darauf basierend. Ich werde meinen Beitrag aktualisieren, wenn es fertig ist. – RPFeltz