1位符号位+5位指数位+10位尾数位,共16位,内存占2个字节,表示方式为(-1)^s * 2 ^(e - 15) * 1.f
在这里以int转fp16为例
int data[5] = {30,256, 0, -1,-256};
//十六进制为0x0000001e,二进制为:0x0000 0000 0000 0000 0000 0000 0001 1110
//二进制科学计数法为1.110*2^4 sign:0,exponent:4, fraction:110
//
int* intToFp16(int* data, int len)
{
int fp16Res[5] = {0};
for(int i = 0; i < len, i++)
{
int sign, exp, mant; //符号位、指数位、尾数位
int bitsNum = 31;
long dataLong = ((data[i] >= 0) ? data[i] : (-data[i])); //取绝对值,拓展为long是因为下面不断左移过程中会超出int表示范围
sign = (data[i] >> 31) & 0x01; //最高位为符号位
exp = 30; //int为4字节,除去符号位,最大表示为2^30
if(data[i] == 0) return 0;
while(bitsNum > 0)
{
int curBit;
dataLong <<= 1;
curBit = (dataLong >> 31) & 0x01;
if(curBit) //找到最高非0位
{//此时data:1111 0000 0000 0000 0000 0000 0000 0000
mant = (dataLong >> 21) & 0x3ff; //总共32位,右移21位,剩11位,其中10位为尾数,因此与上0x3ff
break;
}
else
{
exp--;
}
bitsNum--;
}
exp += 15;
fp16Res[i] = (sign << 15) | (exp << 10) | mant;
}
return fp16Res;
}
//结果为fp16Res[5] = {0x4f80, 0x5c00, 0x00, 0xbc00, 0xdc00}