Tôi muốn thực hiện một chức năng trong tinh khiết Lua mà tạo ra một phần (23 bit), một mũ (8 bit), và một dấu (1 bit) từ một số, sao cho số đó xấp xỉ bằng math.ldexp(fraction, exponent - 127) * (sign == 1 and -1 or 1)
và sau đó gói các giá trị được tạo thành 32 bit.Lua - đóng gói IEEE754 đơn chính xác số dấu chấm động
Một chức năng nhất định trong thư viện toán học làm tôi chú ý:
Chức năng frexp phá vỡ giá trị dấu chấm động (v) vào một mantissa (m) và một số mũ (n), như vậy mà giá trị tuyệt đối của m lớn hơn hoặc bằng 0,5 và nhỏ hơn 1,0, và v = m * 2^n.
Lưu ý rằng math.ldexp là hoạt động nghịch đảo.
Tuy nhiên, tôi không thể nghĩ ra cách nào để đóng gói đúng số nguyên. Khi phần định trị được trả về bởi hàm này không phải là số nguyên, tôi không chắc liệu tôi có thể sử dụng nó không.
Có cách nào hiệu quả để thực hiện điều gì đó tương tự như math.frexp()
trả về số nguyên làm phần định trị không? Hoặc là có lẽ một cách tốt hơn để đóng gói số trong định dạng dấu chấm động đơn chính xác IEEE754 trong Lua?
Cảm ơn bạn trước.
Sửa
Tôi xin trình bày (hy vọng) phiên bản cuối cùng của chức năng tôi đã thực hiện:
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
tôi cải thiện cách sử dụng các bit ngầm và thêm hỗ trợ thích hợp cho các giá trị đặc biệt như vậy như NaN và vô cùng. Tôi dựa trên định dạng của tập lệnh liên quan đến.
Tôi cảm ơn cả hai bạn vì lời khuyên tuyệt vời của bạn.
Cảm ơn bạn, tôi vừa kiểm tra nó. Phương pháp nó sử dụng rất giống với phương pháp của tôi, nhưng sử dụng định dạng sạch hơn. Tuy nhiên, có một vài vấn đề với nó (nó dường như không hỗ trợ số không hoặc số rất nhỏ), vì vậy tôi đang làm phiên bản của riêng tôi dựa trên nó. Tôi sẽ cập nhật bài đăng của mình khi hoàn thành. – RPFeltz