从没有 FPO 的定点整数重建 IEEE754 浮点二进制
Reconstruct an IEEE754 floating point binary from a fixed point integer without FPO
我有一个使用定点数的程序,因为我使用的 CPU 不支持 IEEE754 浮点数。
我一直做得很好,首先通过找到指数将标准 IEEE754 转换为定点,然后通过手动访问内存中所述 IEE754 浮点数的位来移动数字等。转换后,我可以进行定点计算了。
但是,是否可以在没有 FPO 的情况下将不动点(比如 Q15.16 整数)重建回 IEE754 浮点数,以便 CPUs 支持 IEEE754/FPO 能够把它当作他们的原生浮点类型来读? CPU 的 FPO 单元实际上如何在原始字节操作中进行这种转换的任何代码或示例,或者它只是一些无法在软件中完成的黑魔法?显然,我不是在寻找超精确的转换。
到目前为止我看到的所有答案都使用 FPO。例如,通过首先计算已经需要 FPO 的 2^(-num_fraction_bits_in_fixed),然后将固定点缩放到该缩放因子。
编辑:通过使用 EOF 的答案作为基线,我能够创建以下代码片段,用于从定点整数重建 IEEE754 浮点数(在此示例中,定点是 Q31.32,存储在INT64)。最后,我只是手动处理了 0 的情况,因为如果没有它,代码实际上会 return 一个非常小的,但仍然是一个非零值。
代码如下:
static INT32 count_exponent(UINT64 x)
{
INT32 l = -33;
for (UINT64 i = 0; i < 64; i++)
{
UINT64 test = 1ULL << i;
if (x >= test)
l++;
else
break;
}
return l;
}
UINT32 float_from_fix32(INT64 value)
{
INT64 original_num = (INT64)value;
UINT64 sign = 0;
if (value < 0)
sign = 1;
// remove the signed bit if it's set
INT64 unsigned_ver = value < 0 ? -value : value;
// calculate mantissa
int lz = nlz(unsigned_ver);
UINT64 y = unsigned_ver << (lz + 1);
// Our fixed-point is 64bits wide. 8 is the exponent bits for IEEE754
UINT64 mantissa = y >> (33 + 8);
// get the non-fractal bits, add the exponent bias ( 127 in IEEE754 )
UINT64 non_fractal = (unsigned_ver >> 32);
UINT64 exp = count_exponent(unsigned_ver) + 127;
// construct the final IEEE754 float binary number
// first add the last 23 bits (mantissa)
UINT32 ret = mantissa;
// add exponent
ret |= (exp << 23);
// special case of 0
if(mantissa == 0 && non_fractal == 0)
ret = 0;
// add the sign if needed
if (sign)
ret |= 0x80000000;
return ret;
}
在不失一般性的情况下,考虑无符号定点数 x
,假设(此处失去一般性)定点格式中的每个数字都是(由)浮点数的归一化浮点数(表示)点格式:
1) 找到前导零的数量 n
(可能有特殊的 CPU 指令可以快速完成此操作且无需(软件)循环)。
2)将数字左移(y = x << n+1
)(产生归一化的浮点数尾数),再右移(m = y >> (signbit+exponentbits)
),这就是浮点数的尾数。
3) 取你的n
,减去定点格式的非小数位数,加上浮点格式的指数偏差。将偏置指数移动到定点结果的指数位位置。
4) 如果原始数字不是无符号的,则在结果中设置符号位,前提是数字是负数。
a) 如果定点数是有符号的v
,则转为unsginedu
,单独保留符号s
(可以复制到符号位直接浮点数)。上述算法的无符号输入将是 x = v < 0 ? -u : u
.
b) exponentbits
取决于浮点数格式。对于ieee754 32位float
,就是8
.
c) 定点格式通常用 n
位的整数表示数字,该整数(概念上)除以常数 2^m
。非小数位(如果存在)是位 n - m
if n > m
。
d) exponent bias
再次用浮点格式描述。对于ieee754 32位float
,偏差为127
.
我有一个使用定点数的程序,因为我使用的 CPU 不支持 IEEE754 浮点数。
我一直做得很好,首先通过找到指数将标准 IEEE754 转换为定点,然后通过手动访问内存中所述 IEE754 浮点数的位来移动数字等。转换后,我可以进行定点计算了。
但是,是否可以在没有 FPO 的情况下将不动点(比如 Q15.16 整数)重建回 IEE754 浮点数,以便 CPUs 支持 IEEE754/FPO 能够把它当作他们的原生浮点类型来读? CPU 的 FPO 单元实际上如何在原始字节操作中进行这种转换的任何代码或示例,或者它只是一些无法在软件中完成的黑魔法?显然,我不是在寻找超精确的转换。
到目前为止我看到的所有答案都使用 FPO。例如,通过首先计算已经需要 FPO 的 2^(-num_fraction_bits_in_fixed),然后将固定点缩放到该缩放因子。
编辑:通过使用 EOF 的答案作为基线,我能够创建以下代码片段,用于从定点整数重建 IEEE754 浮点数(在此示例中,定点是 Q31.32,存储在INT64)。最后,我只是手动处理了 0 的情况,因为如果没有它,代码实际上会 return 一个非常小的,但仍然是一个非零值。
代码如下:
static INT32 count_exponent(UINT64 x)
{
INT32 l = -33;
for (UINT64 i = 0; i < 64; i++)
{
UINT64 test = 1ULL << i;
if (x >= test)
l++;
else
break;
}
return l;
}
UINT32 float_from_fix32(INT64 value)
{
INT64 original_num = (INT64)value;
UINT64 sign = 0;
if (value < 0)
sign = 1;
// remove the signed bit if it's set
INT64 unsigned_ver = value < 0 ? -value : value;
// calculate mantissa
int lz = nlz(unsigned_ver);
UINT64 y = unsigned_ver << (lz + 1);
// Our fixed-point is 64bits wide. 8 is the exponent bits for IEEE754
UINT64 mantissa = y >> (33 + 8);
// get the non-fractal bits, add the exponent bias ( 127 in IEEE754 )
UINT64 non_fractal = (unsigned_ver >> 32);
UINT64 exp = count_exponent(unsigned_ver) + 127;
// construct the final IEEE754 float binary number
// first add the last 23 bits (mantissa)
UINT32 ret = mantissa;
// add exponent
ret |= (exp << 23);
// special case of 0
if(mantissa == 0 && non_fractal == 0)
ret = 0;
// add the sign if needed
if (sign)
ret |= 0x80000000;
return ret;
}
在不失一般性的情况下,考虑无符号定点数 x
,假设(此处失去一般性)定点格式中的每个数字都是(由)浮点数的归一化浮点数(表示)点格式:
1) 找到前导零的数量 n
(可能有特殊的 CPU 指令可以快速完成此操作且无需(软件)循环)。
2)将数字左移(y = x << n+1
)(产生归一化的浮点数尾数),再右移(m = y >> (signbit+exponentbits)
),这就是浮点数的尾数。
3) 取你的n
,减去定点格式的非小数位数,加上浮点格式的指数偏差。将偏置指数移动到定点结果的指数位位置。
4) 如果原始数字不是无符号的,则在结果中设置符号位,前提是数字是负数。
a) 如果定点数是有符号的v
,则转为unsginedu
,单独保留符号s
(可以复制到符号位直接浮点数)。上述算法的无符号输入将是 x = v < 0 ? -u : u
.
b) exponentbits
取决于浮点数格式。对于ieee754 32位float
,就是8
.
c) 定点格式通常用 n
位的整数表示数字,该整数(概念上)除以常数 2^m
。非小数位(如果存在)是位 n - m
if n > m
。
d) exponent bias
再次用浮点格式描述。对于ieee754 32位float
,偏差为127
.