⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myfloat.c

📁 纯C写的48位软件模拟浮点运算,可移植 测试版
💻 C
📖 第 1 页 / 共 4 页
字号:
				{
					// 规格化处理
					// 这时需先左移mh, 再左移ml,ml左移出的位放到mh
					U8 fmtmhsubt;
					U8	i=0;
					fmtmhsubt = fmtmhsub;
					while ( fmtmhsubt < 0x80 ) // 说明高8位尾数高位不为1了 
					{
						fmtmhsubt = fmtmhsub << (++i);
					}
					//左移个数为i
					//fmtmhsub = fmtmhsubt;//得到左移后的高8位mh结果
					// 从ml 要移到mh的位 | fmtmhsub
					fmtmhsub =(U8)( fmtmhsubt | ((U8)( fmtmlsub >> ( 32 - i ))));
					fmtmlsub = (fmtmlsub << i);
					if ( fet1 < (-64 +  i ) )//说明出现下溢,当0处理 
					{
						ft.s =0;
						ft.e =0;
						ft.mh =0;
						ft.ml =0;
						return ( ft );
					}
					else
					{
						ftesub = fet1 - i;
						ft.s =0;
						// ftesub要处理为7位的补码
						if ( 0x80 == (ftesub &0x80) )// 负指数
						{
							ftesub=(U8)(( ftesub& 0x3f ) |0x40 );
						}
						ft.e =ftesub;
						ft.mh = fmtmhsub;
						ft.ml = fmtmlsub;
						return ( ft );
					}

				}// (fmtmlsub <>0 )end 
			}// fmtmhsub <>0 ,尾数的高8位不等于0 end 

		}
	}

	// 保证ft1中为指数较大的大数,ft2中为指数较小的数
	ft.s = 0; // 初始为0,即为正,默认为fet1>fet2
	if ( fet1 < fet2 )
	{
		S8 t;

		ft1 = b;
		ft2 = a;
		t=fet1;
		fet1=fet2;
		fet2=t;
		ft.s= 1;	//结果为负数
	}

	if ( fet1 > fet2 )// 指数不相同,指数右移,尾数相减,有借位问题,
	{
		fmt2ml = ft2.ml;
		fmt2mh = ft2.mh;
		fmt1ml = ft1.ml;
		fmt1mh = ft1.mh;

		fet = fet1 - fet2;
		if ( fet >=8 ) // 减数ft1的指数大于被减数ft2指数超过8,即要移的位多于8位,这时ft2尾数的高位mh即右移位后全为0
		{//fmt2mh
			fmt2ml = ( ft2.ml >> fet );// ft2.ml 右移
			fmt2mh32 = ( (U32)ft2.mh )<< (32 -fet ); //ft2.mh 的8个位移到ft2.ml的左边
			fmt2ml = fmt2mh32 | fmt2ml; //拼装成右移好的新的ft2的尾数(全在32位中,因fet>=8)
			fmt2mh = 0; // 因为8位全右移走了.
		}
		if ( ( fet >0 ) && ( fet < 8 ) )  //即0<fet<8 时,这时ft2
		{
			fmt2ml = ( ft2.ml >> fet );// ft2.ml 右移

			//ft2.mh 先左移8-fet后就除去了高位不需要移入ml的高位的部分,
			//然后转成U32再左移24位,这样就移到U32位的最高位,即ml的最高位,
			fmt2mh32 =( (U32) ( (U8)(ft2.mh << (8 -fet ) ) ) )<< 24; 

			fmt2ml = fmt2mh32 | fmt2ml; //拼装成右移好的新的ft2的尾数
			
			// ft2.mh 右移fet,得到新右移后的mh的尾数
			fmt2mh = (U8) ( ft2.mh >> fet );
		}
		// ft1和ft2的尾数相减
		if ( fmt1ml < fmt2ml ) // 低32位就要有借位如a-b= 9- ( b- a)+1 ;
		{
			// 计算低32位
			fmt1mlt = fmt2ml - fmt1ml;
			fmtmlsub = (0xffffffff - fmt1mlt) +1;
			fmtmlC = 1;// 借位
		}
		else
		{
			fmtmlsub = fmt1ml - fmt2ml;
			fmtmlC = 0;
		}
		// 计算高8位
		fmt1mht = fmt1mh - fmtmlC;
		//由于ft1>ft2,所以ft1的尾数是从二进制数0.1开始的,而ft2的尾数向右移了的所以ft2的尾数至少是<=0.01(二进制数)的
		//所以fmt1mht-fmt2mh是不可能需要向高位借位的,也就是不需要从指数借位
		fmtmhsub = fmt1mht - fmt2mh;//
		//////////////////////////////////////////////
		// 规格化处理(尾数左移使mh最高位应为1)
		///////////////////////////////////////////////
		//fmtmhsub是不可能为0的,因为二进制数(0.1 - 0.01 )= 0.01,其结果是要>0.01的(二进制数) 
		// fmtmhsub <>0 ,尾数的高8位不等于0
		if ( 0 == fmtmlsub )// 低32位为0,只用处理高8位mh了
		{
			U8 fmtmhsubt;
			U8	i=1;
			
			fmtmhsubt = fmtmhsub;
			while (( fmtmhsubt < 0x80 )&&( fmtmhsubt !=0 )) // 说明高8位尾数高位不为1了 
			{
				fmtmhsubt = fmtmhsub << (i++);
			}
			//左移个数为i-1
			fmtmhsub = fmtmhsubt;//得到左移后的高8位mh结果
			if ( fet1 < (-64 + ( i -1 ) ) )//说明出现下溢,当0处理 
			{
				ft.s =0;
				ft.e =0;
				ft.mh =0;
				ft.ml =0;
				return ( ft );
			}
			else
			{
				ftesub = fet1 - ( i-1);
				
				// ftesub要处理为7位的补码
				if ( 0x80 == (ftesub &0x80) )// 负指数
				{
					ftesub=(U8)(( ftesub& 0x3f ) |0x40 );
				}

				ft.e =ftesub;
				ft.mh = fmtmhsub;
				ft.ml = fmtmlsub;
				return ( ft );
			}
		}
		else // (fmtmlsub <>0 )
		{
			// 规格化处理
			// 这时需先左移mh, 再左移ml,ml左移出的位放到mh
			U8 fmtmhsubt;
			U8	i=0;
			fmtmhsubt = fmtmhsub;
			while (( fmtmhsubt < 0x80 )&&( fmtmhsubt !=0 )) // 说明高8位尾数高位不为1了 
			{
				fmtmhsubt = fmtmhsub << (++i);
			}
			//左移个数为i
			//fmtmhsub = fmtmhsubt;//得到左移后的高8位mh结果
			// 从ml 要移到mh的位 | fmtmhsub
			fmtmhsub =(U8)( fmtmhsubt | ((U8)( fmtmlsub >> ( 32 - i ))));
			fmtmlsub = (fmtmlsub << i);
			if ( fet1 < (-64 +  i ) )//说明出现下溢,当0处理 
			{
				ft.s =0;
				ft.e =0;
				ft.mh =0;
				ft.ml =0;
				return ( ft );
			}
			else
			{
				ftesub = fet1 - i;
				
				// ftesub要处理为7位的补码
				if ( 0x80 == (ftesub &0x80) )// 负指数
				{
					ftesub=(U8)(( ftesub& 0x3f ) |0x40 );
				}
				ft.e =ftesub;
				ft.mh = fmtmhsub;
				ft.ml = fmtmlsub;
				return ( ft );
			}
		}// (fmtmlsub <>0 )end 
	}
	return ( ft );

}

// myfloat类型乘法
// 要有一个80位的中间变量来存放中间移位加的结果
myfloat MyfloatMul( myfloat a, myfloat b )
{
	xdata myfloat ft;
	xdata myfloat ft1,ft2;
	// 中间变量:高位到低位,temp1 temp2 temp3 temp4
	xdata U8 temp1,temp3,ftmh,ftmllC,ftmlhC,ftmhlC,ftmhhC,ft2Bit,fettemp,ftm5;
	xdata U32 temp2,temp4,ftml;
	xdata S8		fet;
	xdata S8      fet1;
	xdata S8		fet2;
	xdata S8		i,j;

	ft1 =a;
	ft2 =b;
	fet1 = ft1.e;
	fet2 = ft2.e;
	// 乘数为0处理
	if ((( ft1.mh == 0 ) && (ft1.ml == 0 ) )||
		(( ft2.mh == 0 ) && (ft2.ml == 0 ) ))
	{
		ft.s = 0;
		ft.e = 0;
		ft.mh = 0;
		ft.ml = 0;
		return ( ft );
	}
	// 判断指数的正负
	if ( (ft1.e & BIT_MASKES) == BIT_MASKES )
	{
		fet1 = (S8)( 0x80 |( (U8) ( ~( (~ft1.e + 1 ) & 0x3f ) +1 ) ) ); 	// 得到原码,再求补码,由六位真值变七位真值
	}
	if ( (ft2.e & BIT_MASKES) == BIT_MASKES  )		
	{
		fet2 = (S8)( 0x80 |( (U8) ( ~( (~ft2.e + 1 ) & 0x3f ) +1 ) ) ); 	// 得到原码,再求补码,由六位真值变七位真值
	}
	// 保证ft1中为指数较大的大数,ft2中为指数较小的数
	// fet1 ,fet2 是真值,即是绝对值
	if ( fet1 < fet2 )
	{
		S8 t;

		ft1 = b;
		ft2 = a;
		t=fet1;
		fet1=fet2;
		fet2=t;
	}
	// 方法:需左移操作的尾数放入80位临时变量中,先左移一位,若下一位为1加上自身再左移,若为0,直接左移,
	// 然后若下位为1加自身左移,为0直接左移. 依此下去处理完所有40位
	temp1 = 0;
	temp2 = 0;
	temp3 = ft1.mh;
	temp4 = ft1.ml;
	ftmh = ft1.mh;
	ftml = ft1.ml;
	
	ftmhhC = 0;
	for ( i = 1 ; i <= 40-1 ; i++ )// 再左移fet2-2次即移完了,共移了fet2-1次
	{
		SL80(&temp1,&temp2,&temp3,&temp4);// 80位数左移一位
		// 初始化,ftmhhC是向指数位进位的,不能在这初始化
		ftmhlC=ftmlhC=ftmllC = 0;
		//得到相应的位的位值
		if ( i< 8)//处理ft2.mh
		{
			ft2Bit =(U8)(( ft2.mh >> (7-i) ) & 0x01 ) ;
		}
		else// 处理ft2.ml
		{
			ft2Bit =(U8)(( ft2.ml >> (39-i )) & 0x00000001 );
		}

		if ( 1== ft2Bit )
		{
			temp4 = temp4 + ftml;
			if ( temp4 < ftml ) // 说明有进位
			{
				ftmllC = 1;
			}
			else
			{
				ftmllC = 0;
			}
			temp3 = temp3 + ftmh;
			if ( temp3 < ftmh ) // 说明有进位
			{
				ftmlhC = 1;
				temp3 = temp3 + ftmllC;//因为temp3+ftmh已有进位所以再加上1后不会再产生新的进位
				
			}
			else
			{
				ftmlhC = 0;
				if ( 1 == ftmllC )
				{
					temp3 = temp3 + ftmllC;// 因为temp3+ftmh未产生进位,这时再加ftmlh还是有可能产生进位
					if ( temp3 < ftmllC )
					{
						ftmlhC = 1;
					}
					else
					{
						ftmlhC = 0;
					}
				}
				else
				{
					temp3 = temp3;
				}
			}

			// 处理ftmhl区相加问题
			if ( ftmlhC == 1 )
			{
				temp2 = temp2 + ftmlhC;
				ftmhlC= 0;//默认
				if ( temp2 < ftmlhC )// 就有进位,实际上也只有temp2= 0xffffffff时才可能有进位
				{
					ftmhlC = 1;
				}
				// 处理ftmhh区
				if ( 1==ftmhlC )//有进位
				{
					temp1 = temp1 + ftmhlC;
					ftmhhC = 0;//默认
					if ( temp1 < ftmhlC )// 有进位
					{
						ftmhhC = 1; // 这个进位是用于给指数的了
					}
				}
			}
		}// 为1
	}
	// 积做四舍五入
	// 从80位中,左边开始找1找到1到继续找之后41位上是否为1,为1则四舍五入
    // 80位数据继续左移直到移到temp1的最高位为止
	for ( i = 1; i <= (41- fet2); i++)
	{
		if ( i<=8)
		{
			if ( 1==((temp1 >> ( 8-i) ) &0x01 ))// 在temp1找到了1
			{
				// 接着找之后40位是否是1,U8U32 U8 所以第41位在temp3中
				if (1==( temp3 >> (8-i ) &0x01 ) )// 则需要五入
				{
					ftm5 = 1;// 需要在将来40位的最后一位加1
				}
				else
				{
					ftm5 = 0;
				}
				break;
			}
		}
		else
		{
			if ( 1==((temp2 >> ( 40-i) ) &0x01 ))// 在temp2找到了1
			{
				if ( i < 40)
				{
					if (1==( temp4 >> (40-i ) &0x01 ) )// 则需要五入
					{
						ftm5 = 1; // 需要在将来40位的最后一位加1
					}
					else
					{
						ftm5 = 0; 
					}
				}
				break;
			}

		}

	}
	//先左移到最高位规格化
	for ( j = 1; j<=(i-1); j++)
	{
		SL80(&temp1,&temp2,&temp3,&temp4);// 80位数左移一位
	}

	fettemp =(i-1) -ftmhhC;// fettemp是需要减去的指数个数,加上规格化中左移(i-1)次,(包括了ftmhhC(向指数进位的位))

	// 只要temp1和temp2中的数据
	if ( 1== ftm5 )//要四舍五入
	{
		temp2= temp2 +1;
		if ( temp2 < 1 )//有进位
		{
			temp1 = temp1 + 1;
			if ( temp1 < 1 )// 有进位
			{
				ftmhhC += 1;// 若先就有进位到指数的话,这里实际上不可能有进位了,ftmhhC =1这样写也没错
				// 实际只有40位全为1时,加1才可能产生ftmhhC的进位,而这时,才会出现要求重规格化
				//而这时fettemp= fettemp + 39, temp1 = 0x80,temp2 =0x00000000;
				fettemp +=39;
				temp1 = 0x80; 
				temp2 = 0;
			}
			
			
		}
		

	}
	// 求目前规格化后的数据
	ft.s = ((((~ft1.s) & 0x01) & ft2.s) | (((~ft2.s) & 0x01) & ft1.s));// 异或求ft.s
	//ft1.e,ft2.e 要换成8位的有符号数然后再算,判断超出范围吗?算完了就变为七位的有符号数,
	// 七位=>8位有符号数转化
	fet1 = ft1.e;
	fet2 = ft2.e;
	S7ToS8( &fet1 );
	S7ToS8( &fet2 );
	fet =(fet1 +fet2 - fettemp) ;
	// 默认-64<=fet<=63
	S8ToS7( &fet );
	ft.e = (U8)fet;
	
	if ( fet> 63)// 上溢
	{
		//减小到指数为63时的值,所以一旦溢出,数据就是不定的了!
		ft.e = 63;

	}
	if (fet < -64 )//下溢
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -