半精度浮点数和单精度浮点数的转换(不考虑特殊情况)

        面试问题是要求写两个函数,一个函数要求将输入得浮点数转换为半精度浮点数,也就是32位float的浮点转为16位浮点数,然后另外一个函数是要求把16位浮点数转换为32位浮点数。

      关于浮点数的详细介绍参考:https://blog.csdn.net/whyel/article/details/81067989。浮点数其实就是由三个部分构成,总体思路便是从这三个部分去思考,并且截断做转换。如果有发现不对的地方,欢迎指出。

  

#include 
#include 

const int Sbit_2_9 = 0b11111111 << 23;
const short Sbit_2_6 = 0b11111 << 10;

const int bit32_0 = 0b1 << 31;
const int bit16_0 = 0b1 << 15;

const int Sbit_10_32 = ~(0b111111111 << 23);
const short Sbit_7_16 = ~(0b111111 << 10);

/*
	float_2_half: float to half
	由于c++中没有半精度浮点数类型
	所以采用16位的short来表示16位的半精度浮点数
*/
short float_2_half(float num)
{
	//因为要对float的符号位,指数位和尾数三个部分操作,所以要对float类型做位运算
	//但是float无法做位运算,所以把int类型指针指向float
	int *pval = reinterpret_cast(&num);
	int bit_num = *pval;

	//取符号位
	bool sign = bit_num&bit32_0;
	//取指数位和尾数
	int bit_2_9 = (Sbit_2_9&bit_num)>>23;
	int bit_10_32 = Sbit_10_32&bit_num;

	//将指数位减去偏置127,再加上半精度精度的偏置18
	//半精度浮点数: 1 符号位  5 指数位 10尾数,所以最后还要右移十位
	short bit_2_6 = (bit_2_9-127+18) <<10;

	//尾数从23位表示降到了10位表示,不考虑特殊情况,这里需要保留高位并直接对低位截断(去掉低13位)
	short bit_7_16 = bit_10_32  >> (23-10);

	//合并 符号位 指数位和尾数,保存在16位的short中,表示半精度的机器码
	short ans = sign << 15 |bit_2_6 | bit_7_16 ;
	return ans;
}

float half_2_float(short num)
{
	bool sign = num &bit16_0;

	short bit_2_6 = ( num&Sbit_2_6 ) >> 10;
	short bit_7_16 = num & Sbit_7_16;

	int bit_2_9 = ((bit_2_6 - 18+127) << 23)&Sbit_2_9;
	int bit_10_23 = bit_7_16 << (23-10);

	int ans = sign << 31 |bit_2_9 | bit_10_23  ;
	float *p_float = reinterpret_cast (&ans);

	return *p_float;
}

int main()
{
	float t = -0.124;
	short tmp = float_2_half(t);
	float re = half_2_float(tmp);
	std::cout << re << std::endl;
    return 0;
}

      这是阿里平头哥面试官的代码问题,自以为自己已经懂浮点数得基本原理了,经过这一次发现:只是自己以为自己懂浮点数原理了,不由得反思:平时学习不够认真。

        最后,感谢平头哥的面试官。

        

你可能感兴趣的:(秋招)