Lua - упаковка чисел с плавающей точкой одинарной точности IEEE754

Я хочу сделать функцию в чистом Lua, которая генерируетдоля (23 бита),показатель степени (8 бит) изнак (1 бит) от числа, так что число приблизительно равноmath.ldexp(fraction, exponent - 127) * (sign == 1 and -1 or 1), а затем упаковывает сгенерированные значения в 32 бита.

Определенная функция в математической библиотеке привлекла мое внимание:

Функция frexp разбивает значение с плавающей точкой (v) на мантиссу (m) и экспоненту (n), так что абсолютное значение m больше или равно 0,5 и меньше 1,0, а v = m * 2 ^ п.

Обратите внимание, что math.ldexp является обратной операцией.

Тем не менее, я могуНе придумайте, как правильно упаковать нецелые числа. Поскольку мантисса, возвращаемая этой функцией, не является целым числом, яЯ не уверен, что смогу это использовать.

Есть ли эффективный способ сделать что-то похожее наmath.frexp() который возвращает целое число как мантисса? Или, возможно, есть лучший способ упаковать числа в формате с плавающей запятой IEEE754 с одинарной точностью в Lua?

Заранее спасибо.

редактировать

Настоящим я представляю (надеюсь) окончательную версию функций, которые я сделал:

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
            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 и бесконечность. Я основал форматирование на том сценарии, который связан с.

Я благодарю вас обоих за отличный совет.

Ответы на вопрос(2)

Ваш ответ на вопрос