提问人:Mike 提问时间:1/17/2023 最后编辑:Daniel W.Mike 更新时间:1/17/2023 访问量:227
将 IEEE-754 16 位浮点数打包为 16 位无符号整数,同时保持顺序
Packing an IEEE-754 16-bit float to a 16-bit unsigned integer while preserving order
问:
我有一个 IEEE-754 16 位浮点数,我想将其无损打包为 16 位无符号整数。当然,最简单的方法是打包它的字节,然后解压缩它,但问题是我需要在程序中比较 16 位整数(即大于、小于等)。所以我正在寻找 f16 和 u16 之间的同构来保持秩序。谁能建议一种算法来做到这一点?谢谢!
答:
3赞
chux - Reinstate Monica
1/17/2023
#1
要使用整数数学来维护 float16,请将数据视为使用符号大小编码的有符号整数。<, ==, >
使用 和 执行此操作以获得正确的代码(因为并非所有代码都可用),然后针对 16 位进行调整。float
(u)int32_t
float16_t
将负值否定为正值,并将 MSBit 设置为正值。
确保 +0.0 和 -0.0 转换为相同的值。
// Assumes same endian for FP and integers
#include <float.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
// Assumes same endian for FP and integers
unsigned float_to_sequence(float f) {
union {
float f;
int32_t i;
uint32_t u;
} x = {.f = f};
if (x.i < 0) {
x.u = -x.u;
} else {
x.u |= 0x80000000;
}
return x.u;
}
测试
void test(float f) {
printf("%+-20a %+-18.9e ", f, f);
printf("0x%08X\n", float_to_sequence(f));
}
int main(void) {
float f[] = {-INFINITY, -FLT_MAX, -1.0, -FLT_TRUE_MIN, -0.0, //
0.0, FLT_TRUE_MIN, 1.0, FLT_MAX, INFINITY};
size_t n = sizeof f / sizeof f[0];
for (size_t i = 0; i < n; i++) {
test(f[i]);
}
}
输出
-inf -inf 0x00800000
-0x1.fffffep+127 -3.402823466e+38 0x00800001
-0x1p+0 -1.000000000e+00 0x40800000
-0x1p-149 -1.401298464e-45 0x7FFFFFFF
-0x0p+0 -0.000000000e+00 0x80000000
+0x0p+0 +0.000000000e+00 0x80000000
+0x1p-149 +1.401298464e-45 0x80000001
+0x1p+0 +1.000000000e+00 0xBF800000
+0x1.fffffep+127 +3.402823466e+38 0xFF7FFFFF
+inf +inf 0xFF800000
转换是一一,除了 +0.0 和 -0.0 都转换为相同的值 - 它应该这样做。
对于 16 位单行:uint16_t y = (x & 0x8000) ? -x : (x | 0x8000);
评论
(x & 0x8000) ? (0x8000 | (0x8000 - (x & 0x7fff))) : x
0x7fff
0x8000
(x & 0x8000) ? 0x7fff - (x & 0x7fff) : 0x80000 | x
+0 > -0