单精度浮点数 二进制的转换 C++实现

//将单精度浮点数,转换为十进制
string MySystem::FloatToBinaryByMemory(float num)
{
	<span style="color:#ff0000;">//只用内存中的结构来输出二进制结果</span>
	unsigned char *p = (unsigned char *)(&num);
	string Result("");
	for (int i = sizeof(num)-1;i>=0;--i)                     //这里使用的是小端机器,对于大端法的机器,可以使用 i=0;i<sizeof(num)-1;++i
	{
		//将unsigned char 转换为 二进制
		string temp(8, '0');//保存每个字节的二进制表示
		int Index = temp.size() - 1;
		unsigned char ch = p[i];
		while (ch)
		{
			temp[Index]=ch % 2+'0';
			ch /= 2;
			--Index;
		}
		Result += temp;
	}
	return Result;
}


//将单精度浮点数转换为二进制---------分析原理
string MySystem::FloatToByBinaryByAlgo(float num)
{
	//	(-1) s表示符号位,当s = 0,V为正数;当s = 1,V为负数。  
	//	(2)M表示有效数字,大于等于1,小于2。
	//	(3)2^E表示指数位。
	//对于单精度 符号位 1 指数为8    有效数字 23
	string sign = (num < 0) ? "1" : "0";
	num = abs(num);
	//将float分解成正数部分和小数部分
	int Interger = int(num);
	float frac = num - Interger;
	//将其转换为分别转换为二进制的数字
	string IntStr("");
	string FracStr("");
	//转换正数部分
	while (Interger)
	{
		IntStr += (Interger % 2 + '0');
		Interger /= 2;
	}
	//翻转字符串
	int i = 0;
	int j = IntStr.size() - 1;
	while (i < j)
	{
		swap(IntStr[i], IntStr[j]);
		++i;
		--j;
	}
	string EStr(8, '0');             //指数域
	string MStr("");				//小数域
	//分解小数部分----由于小部分,可能会出现分解不完全的情况,并且float中仅有23位,所以仅仅循环23次------但是对于仅有小数的部分,还要截断一部分,所以需要补充
	for (int i = 1; i < 24+23; ++i)
	{
		if (frac == 0.0)       //如果等于0,那么退出循环
		{
			break;
		}
		float temp = pow(2, -i);
		if (frac >= temp)
		{
			FracStr += '1';
			frac -= temp;
		}
		else
		{
			FracStr += '0';
		}
	}
	if (num>=1.0)
	{
		//准备工作已经完成了,开始进行实际的工作 
		//偏置 BIAS=pow(2,8-1)-1=127;
		int Offset = IntStr.size() - 1 + 127;	
		int Index = 7;
		//指数域
		while (Offset)
		{
			EStr[Index] = Offset % 2 + '0';
			Offset /= 2;
			--Index;
		}
		//那么小数域为;
		MStr = IntStr.substr(1) + FracStr;
	}
	else
	{
		//找到小数的第一个1为位置
		int Index = 0;
		for (int i = 0; i < FracStr.size();++i)
		{
			if (FracStr[i]=='1')
			{
				Index = i + 1;
				break;
			}
		}
		unsigned char Offset = Index?(-Index + 127):0;//如果小数部分没有1的话,那么就是X.0 
		int temp = 7;
		//指数域
		while (Offset)
		{
			EStr[temp] = Offset % 2 + '0';
			Offset /= 2;
			--temp;
		}
		//那么小数域为;
		MStr = FracStr.substr(Index);
	}
	//对字符进行填充
	if (MStr.size() > 23)
	{
		MStr = MStr.substr(0, 23);
	}
	else
	{
		MStr.resize(23);
		for (int i = 0; i < 23; ++i)
		{
			if (MStr[i] == '\0')
			{
				MStr[i] = '0';
			}
		}
	}
	return sign + EStr + MStr;
}

//将二进制的数据,转换为float浮点数
float MySystem::BinaryTofloat(string str)
{
	if (str.size()!=32)
	{
		return NAN;
	}
	//	(-1) s表示符号位,当s = 0,V为正数;当s = 1,V为负数。  
	//	(2)M表示有效数字,大于等于1,小于2。
	//	(3)2^E表示指数位。
	//对于单精度 符号位 1 指数为8    有效数字 23
	//  (1)E不全为0或不全为1。这时,浮点数就采用上面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
	//	(2)E全为0。这时,浮点数的指数E等于1 - 127(或者1 - 1023),有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
	//	(3)E全为1。这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)。
	int sign = (str[0] == '0') ? 1 : -1;
	//分解有效数数字,因为,对于E来说比较复杂,所以我们最后在分解
	float frac = 0.0;
	for (int i = 9; i < str.size();++i)
	{
		frac += pow(2, -i + 8)*(str[i]-'0');
	}
	//分解指数位
	//假如全为0的情况
	bool mark = true;
	for (int i = 1; i < 9;++i)
	{
		if (str[i]=='1')
		{
			mark = false;
			break;
		}
	}
	if (mark)
	{
		return sign*frac*pow(2, 1 - 127);
	}
	//假如全为1的情况
	mark = true;
	for (int i = 1; i < 9;++i)
	{
		if (str[i]=='0')
		{
			mark = false;
			break;
		}
	}
	if (mark)
	{
		if (0.0==frac) //如果M全为0 
		{
			if (1==sign)//那么如果符号为1 的话,返回负无穷
			{
				return -INFINITY;
			}
			else //如果符号为0的话,返回正无穷
			{
				return INFINITY;
			}
		}
		else         //不然的话,返回NAN 不是一个数字
		{
			return NAN;
		}
	}
	//最后一种情况,指数不全为0或者1
	unsigned char p = 0;
	for (int i = 8,Index=0; i >= 1;--i,++Index)
	{
		p += pow(2, Index)*(str[i] - '0');
	}
	float E = pow(2, p - 127);
	return sign*E*(1 + frac);
}


  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值