Lua - 打包 IEEE754 单精度浮点数 [英] Lua - packing IEEE754 single-precision floating-point numbers

查看:84
本文介绍了Lua - 打包 IEEE754 单精度浮点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在纯 Lua 中创建一个函数,生成一个分数(23 位)、一个指数(8 位)和一个符号(1 位)来自一个数,使该数约等于 math.ldexp(fraction, exponent - 127) * (sign == 1 and -1 or 1),然后将生成的值打包成 32 位.

I want to make a function in pure Lua that generates a fraction (23 bits), an exponent (8 bits), and a sign (1 bit) from a number, so that the number is approximately equal to math.ldexp(fraction, exponent - 127) * (sign == 1 and -1 or 1), and then packs the generated values into 32 bits.

数学库中的某个函数引起了我的注意:

A certain function in the math library caught my attention:

frexp 函数将浮点值 (v) 分解为尾数 (m) 和指数 (n),使得 m 的绝对值大于等于 0.5 且小于 1.0,并且 v= m * 2^n.

The frexp function breaks down the floating-point value (v) into a mantissa (m) and an exponent (n), such that the absolute value of m is greater than or equal to 0.5 and less than 1.0, and v = m * 2^n.

注意 math.ldexp 是逆运算.

Note that math.ldexp is the inverse operation.

但是,我想不出任何方法来正确打包非整数.由于这个函数返回的尾数不是整数,不知道能不能用.

However, I can't think of any way to pack non-integer numbers properly. As the the mantissa returned by this function is not an integer, I'm not sure if I can use it.

是否有任何有效的方法可以执行类似于返回整数作为尾数的 math.frexp() 的操作?或者是否有更好的方法在 Lua 中以 IEEE754 单精度浮点格式打包数字?

Is there any efficient way to do something similar to math.frexp() which returns an integer as the mantissa? Or is there perhaps a better way to pack numbers in the IEEE754 single-precision floating-point format in Lua?

提前致谢.

编辑

我在此展示我制作的函数的(希望如此)最终版本:

I hereby present the (hopefully) final version of the functions I made:

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 的格式.

I improved the way to utilise the implicit bit and added proper support for special values such as NaN and infinity. I based the formatting on that of the script catwell linked to.

感谢你们两位的宝贵建议.

I thank both of you for your great advice.

推荐答案

将从 math.frexp() 得到的有效数乘以 2^24,并从指数中减去 24 以进行补偿.现在有效数是一个整数.请注意,有效数是 24 位,而不是 23(您需要考虑 IEEE-754 编码中的隐式位).

Multiply the significand you get from math.frexp() by 2^24, and subtract 24 from the exponent to compensate. Now the significand is an integer. Note that the significand is 24 bits, not 23 (you need to account for the implicit bit in the IEEE-754 encoding).

这篇关于Lua - 打包 IEEE754 单精度浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆