如何将integer
转换为half precision float
(将其存储到数组unsigned char[2]
中)。输入int的范围是1-65535。精确度确实不是问题。
我正在做类似的转换为16bit int
到unsigned char[2]
,但我知道没有half precision float
C ++数据类型。以下示例:
int16_t position16int = (int16_t)data;
memcpy(&dataArray, &position16int, 2);
答案 0 :(得分:4)
这是一件非常简单的事情,您需要的所有信息都在Wikipedia。
示例实施:
#include <stdio.h>
unsigned int2hfloat(int x)
{
unsigned sign = x < 0;
unsigned absx = ((unsigned)x ^ -sign) + sign; // safe abs(x)
unsigned tmp = absx, manbits = 0;
int exp = 0, truncated = 0;
// calculate the number of bits needed for the mantissa
while (tmp)
{
tmp >>= 1;
manbits++;
}
// half-precision floats have 11 bits in the mantissa.
// truncate the excess or insert the lacking 0s until there are 11.
if (manbits)
{
exp = 10; // exp bias because 1.0 is at bit position 10
while (manbits > 11)
{
truncated |= absx & 1;
absx >>= 1;
manbits--;
exp++;
}
while (manbits < 11)
{
absx <<= 1;
manbits++;
exp--;
}
}
if (exp + truncated > 15)
{
// absx was too big, force it to +/- infinity
exp = 31; // special infinity value
absx = 0;
}
else if (manbits)
{
// normal case, absx > 0
exp += 15; // bias the exponent
}
return (sign << 15) | ((unsigned)exp << 10) | (absx & ((1u<<10)-1));
}
int main(void)
{
printf(" 0: 0x%04X\n", int2hfloat(0));
printf("-1: 0x%04X\n", int2hfloat(-1));
printf("+1: 0x%04X\n", int2hfloat(+1));
printf("-2: 0x%04X\n", int2hfloat(-2));
printf("+2: 0x%04X\n", int2hfloat(+2));
printf("-3: 0x%04X\n", int2hfloat(-3));
printf("+3: 0x%04X\n", int2hfloat(+3));
printf("-2047: 0x%04X\n", int2hfloat(-2047));
printf("+2047: 0x%04X\n", int2hfloat(+2047));
printf("-2048: 0x%04X\n", int2hfloat(-2048));
printf("+2048: 0x%04X\n", int2hfloat(+2048));
printf("-2049: 0x%04X\n", int2hfloat(-2049)); // first inexact integer
printf("+2049: 0x%04X\n", int2hfloat(+2049));
printf("-2050: 0x%04X\n", int2hfloat(-2050));
printf("+2050: 0x%04X\n", int2hfloat(+2050));
printf("-32752: 0x%04X\n", int2hfloat(-32752));
printf("+32752: 0x%04X\n", int2hfloat(+32752));
printf("-32768: 0x%04X\n", int2hfloat(-32768));
printf("+32768: 0x%04X\n", int2hfloat(+32768));
printf("-65504: 0x%04X\n", int2hfloat(-65504)); // legal maximum
printf("+65504: 0x%04X\n", int2hfloat(+65504));
printf("-65505: 0x%04X\n", int2hfloat(-65505)); // infinity from here on
printf("+65505: 0x%04X\n", int2hfloat(+65505));
printf("-65535: 0x%04X\n", int2hfloat(-65535));
printf("+65535: 0x%04X\n", int2hfloat(+65535));
return 0;
}
输出(ideone):
0: 0x0000
-1: 0xBC00
+1: 0x3C00
-2: 0xC000
+2: 0x4000
-3: 0xC200
+3: 0x4200
-2047: 0xE7FF
+2047: 0x67FF
-2048: 0xE800
+2048: 0x6800
-2049: 0xE800
+2049: 0x6800
-2050: 0xE801
+2050: 0x6801
-32752: 0xF7FF
+32752: 0x77FF
-32768: 0xF800
+32768: 0x7800
-65504: 0xFBFF
+65504: 0x7BFF
-65505: 0xFC00
+65505: 0x7C00
-65535: 0xFC00
+65535: 0x7C00
答案 1 :(得分:2)
我问过如何将32位浮点转换为16位浮点的问题。
因此,您可以非常轻松地将int转换为float,然后使用上面的问题创建一个16位浮点数。我建议这可能比从int直接转到16位浮点容易得多。通过转换为32位浮点数,你已经完成了大部分的工作,然后你只需要移动几位。
编辑:看看Alexey的优秀答案我认为使用硬件int进行浮动转换然后进行位移可能比他的方法快得多。可能值得分析两种方法并进行比较。
答案 2 :(得分:0)
关注@kbok问题评论后,我使用this answer的第一部分来获取半浮点数然后获取数组:
uint16_t position16float = float_to_half_branch(data);
memcpy(&dataArray, &position16float, 2);
答案 3 :(得分:0)