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

📄 myfloat.c

📁 纯C写的48位软件模拟浮点运算,可移植 测试版
💻 C
📖 第 1 页 / 共 4 页
字号:
		// 指数就为-64 ,数据不定了!
		fet = -64;
		S8ToS7( &fet );
		ft.e = (U8)fet;

	}
	ft.mh = temp1;
	ft.ml = temp2;

	return (ft );
}
#pragma OPTIMIZE ( 0 )
// 40位数左移1位操作
// U8 *mh, U32 *ml, 组成40位数
void SL40( U8 *mh, U32 *ml )
{
	 U8 mht;
	 U32 mlt;

	mht = *mh;
	mlt = *ml;

	
	mht = (U8)((U8)(mht<< 1) | (U8)(mlt >> 31 ));
	mlt = (U32)(mlt << 1 );

	*mh = mht;
	*ml = mlt;
}
// 80位数左移1位操作
// U8 *mhh, U32 *mhl, U8 *mlh, U32 *mll 组成80位数
void SL80( U8 *mhh, U32 *mhl, U8 *mlh, U32 *mll )
{
	 U8 mhht;
	 U32 mhlt;
	 U8 mlht;
	 U32 mllt;
	mhht = *mhh;
	mhlt = *mhl;
	mlht = *mlh;
	mllt = *mll;
	
	mhht = (U8)((U8)(mhht<< 1) | (U8)(mhlt >> 31 ));
	mhlt = (U32)((U32)(mhlt << 1 ) | (U32)( mlht >> 7 ) );
	mlht = (U8)((U8)(mlht<< 1) | (U8)(mllt >> 31 ));
	mllt = (U32)(mllt<< 1 );

	*mhh = mhht;
	*mhl = mhlt;
	*mlh = mlht;
	*mll = mllt;
}
#pragma OPTIMIZE ( 8 )
// 8位符号数到7位符号的转化,例如: 0b10000000 => 0b01000000,7位符号数仍保存在8位中.
// 3位有符号数 -4 --3    000 001 010 011 100( -4) 101( -3) 110 (-2)  111( -1)
// 2位有符号数 -2-- 1    000 001 010 (-2) 011 (-1),
// 3=>2位有符号数 正数不变,  只处理负数
// S8 *e; 输入参数,地址传送
// 保证要转化的S8的数据的范围在S7内,即在-64--63之间,本函数对于超出的数只接截断
void S8ToS7( S8 *e )
{
	U8 te;
	
	te = (U8)(*e);
	// (((U8)(te & 0x80 ))>> 1)得到7位符号数的符号位
	// (te & 0x3f ) 得到6位值部分
	*e = (S8)( (((U8)(te & 0x80 ))>> 1) | ((U8)(te & 0x3f)) );
}

// 7位符号数转8位符号数
void S7ToS8( S8 *e )
{
	U8 te;
	U8 tev;// 真值

	te = (U8)(*e);
	if ( (te & BIT_MASKES) == BIT_MASKES )
	{
		tev = (U8)( 0x80 |( (U8) ( ~( (~te + 1 ) & 0x3f ) +1 ) ) ); 	// 得到原码,再求补码,由六位真值变七位真值
	}
	else
	{
		tev = (U8)(te &0x3f);
	}
	// 符号位与真值相或
	*e = (((U8)((U8)(te << 1 ) & 0x80 )) | (U8)tev );

}

// -1 : x<y 1: x>y 0: x=y
char CmpZ40( U8 xh, U32 xl, U8 yh, U32 yl )
{
	if ( ( xh == yh ) && ( xl == yl )) 
	{
		return ( 0 );
	}

	if ( ( xh < yh ) || ( ( xh== yh ) && ( xl < yl )) )
	{
		return ( -1 );
	}
	else
	{
		return ( 1 );
	}

}
//char MASK[]={ 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 };
// myfloat 除法
myfloat MyfloatDiv( myfloat a, myfloat b )
{
	xdata myfloat ft={0,0,0,0};
	xdata S8 fte;// 暂存指数
	xdata S8 fte1,fte2;
	xdata U8 ftmh;// 商的尾数的高8位,差数的高8位
	xdata U32 ftml;//商的尾数的低32位,差数的低32位
	xdata U8  FlagmhC,FlagmlC;//借位标志
	xdata U8 i,j;
	xdata U32 Exml;
	xdata U8  Exmh;
	xdata U8 mh=0;
	xdata U32 ml=0;
	xdata U8 k; 
	xdata U8 amh,bmh,tmh; // amh是被除数,bmh是除数,tmh是除后的余数 都是高8位
	xdata U32 aml,bml,tml;// 是低32位

	// 初始化
	FLAGOVER = 0;
	FLAGALEB= 0;

	// 除零处理
	if (( 0==b.e ) &&  ( 0 == b.mh ) && ( 0 == b.ml ) )
	{
		ft.s = 0;
		ft.e = 0;
		ft.mh = 0x40;// 用非规格化值表示
		ft.ml = 0;
#ifdef MYDEBUG
///		printf("MYFLOATDIVZERO!!!\n\n");
#endif
		return ( ft );
	}
	// 被除数为0
	if (( 0==a.e ) &&  ( 0 == a.mh ) && ( 0 == a.ml ) )
	{
		ft.s = 0;
		ft.e = 0;
		ft.mh =0;
		ft.ml = 0;
		return ( ft );
	}
	// 初始化
	FlagmhC = 0; //为0无借位,为1有借位
	FlagmlC = 0;
	ftmh = 0;
	ftml = 0;
	i = 0;
	j = 0;
	fte1 = a.e;
	fte2 = b.e;
	S7ToS8( &fte1 );// 转8位有符号数
	S7ToS8( &fte2);

	// 计算指数差(两数相除指数相减)
	fte = fte1- fte2;
	if ( fte < -64 )// 出现下溢,直接做0处理
	{
		ft.s = 0;
		ft.e = 0;
		ft.mh = 0;
		ft.ml = 0;
		return ( ft );
	}
	if ( fte > 63 )// 出现上溢,直接等于最大数
	{
		ft.e = 63;
		ft.s = ((((~a.s) & 0x01) & b.s) | (((~b.s) & 0x01) & a.s));// 异或求ft.s
		ft.mh = 0xff;
		ft.ml = 0xffffffff;
		return ( ft );
	}

    // 按新算法

	//尾数相等
	if ( ( a.mh == b.mh )&&(a.ml == b.ml ))
	{
		fte=fte+1;
		if ( fte > 63 )// 出现上溢,直接等于最大数
		{
			ft.e = 63;
			ft.s = ((((~a.s) & 0x01) & b.s) | (((~b.s) & 0x01) & a.s));// 异或求ft.s
			ft.mh = 0xff;
			ft.ml = 0xffffffff;
			return ( ft );
		}
		S8ToS7(&fte);
		ft.e = fte;
		ft.mh=0x80;
		ft.ml=0x00;
		ft.s = ((((~a.s) & 0x01) & b.s) | (((~b.s) & 0x01) & a.s));// 异或求ft.s

		
		return (ft);
	}
	// a尾数<b尾数
	// 首先要借位所以除出来后商的尾数最高位一定为1,因为被除数尾数最小为0.10000000000000(40位),40位为0x80000000/0xffffffff>0.5
	// 相当于x*2-y,只要进入到FLAGOVER=1下,然后之后就可以用a尾数>b尾数的算法了
	// 但指数fte不用加1
	if ( -1 == CmpZ40( a.mh,a.ml,b.mh,b.ml ) )
	{
		FLAGALEB= 1;
	}

	// a尾数>b尾数
	if ( 1== CmpZ40( a.mh,a.ml,b.mh,b.ml) || ( 1==FLAGALEB   ) )
	{

		ft.s = ((((~a.s) & 0x01) & b.s) | (((~b.s) & 0x01) & a.s));// 异或求ft.s
		if ( 1== FLAGALEB )
		{
			S8ToS7(&fte);
			ft.e=fte; // a>b
		}
		else
		{
			fte=fte+1;
			S8ToS7(&fte);
			ft.e=fte; // 1是因为a>b时,先上了一个1.0000
		}
		// 求商的尾数
		mh=0;
		ml=0;

		amh = a.mh;
		bmh = b.mh;
		aml = a.ml;
		bml = b.ml;

		for ( i =0; i< 40; i++ )
		{
			S8 ij;
			// 除净了(被除数等于除数)
			if ( 0 == CmpZ40( amh,aml,bmh,bml) )
			{
				// 这时还在高8位内
				if ( i < 8 )
				{
					// 商的尾数处理
					mh = mh * 2 + 1;// 先本位商位是要上1的
					// 如果此时i还是小于8
					
					for ( ij = i+1; ij < 8 ; ij++ )
					{
						mh = mh *2 + 0;// 后面的商位都是0
					}
					// 处理低32位
					ml = 0x00000000;

					ft.mh = mh;
					ft.ml = ml;
					return ( ft );

				}
				else
				{
					// 只用处理低32位,高8位已处理完了
					ml = ml * 2 +1; //先本位商位是要上1的
					for ( ij = i+1; ij <40; ij++)
					{
						ml= ml * 2+0;
					}
					ft.mh = mh;
					ft.ml = ml;
					return ( ft );
				}
			}
			
			// 用减法实现处理除法,未除尽前
			// 被除数大于除数时,因为在上面有除数和被除数相等情况的处理,所以、
			// 下面的判断的否则情况只会是被除数小于除数的情况
			if ( 1== CmpZ40( amh,aml,bmh,bml)||( FLAGALEB ==1) ||( 1== FLAGOVER)  )// 步骤1,,加FLAGALEB判断是为进入这个条件语句
			{
				if ( FLAGALEB == 1 )// 当FLAGALEB为1说明是a<b的情况,要直接进入FLAGOVER=1去处理,然后以后和a>b处理一样,所以FLAGOVER=1
				{
					FLAGOVER = 1;
					FLAGALEB = 0;
				}
				if ( FLAGOVER == 0 )
				{
					// 被除数大于除数
					k =1;
					// 尾数相减
					// 低32位
					if ( aml < bml )//那就要借位
					{
						// 如一位十进制数,7-9 要高位借位后=8, 可以表示为9-(9-7)+1 (不能用10,10二位了)
						tml = bml - aml;
						tml = ((U32)0xffffffff - tml) +1; 
						//高8位
						tmh = amh -bmh - 1;
				
					}
					else
					{// tml ,tmh是余数
						tml = aml - bml;
						tmh = amh - bmh;
					}
					amh = tmh;
					aml = tml;
					// 被除数左移一位
					SL40(&amh,&aml);

				}
				if ( FLAGOVER == 1 ) //处理被除数和除数最高位都为1时,仍小于除数的情况
				{
					k= 1;
					// 差= ( E-y+x) -( E- x)
					tml = 0xffffffff - bml;
					tmh = 0xff - bmh;
					// 低32位有进位
					if ( bml < aml )// 说明 E-bml+aml时会有进位
					{
						//则有E-bml+aml = (进位数1)(E-bml+aml -E -1) =(进位1)( aml-bml -1 ),( E+1为进位)
						tml = aml - bml - 1;
						tmh = tmh + amh + 1; //加1是有进位
						
					}
					else
					{
						tml = tml + aml;
						tmh = tmh + amh;
					}
					Exml = 0xffffffff - aml;
					Exmh = 0xff - amh;
					// 如果低32位,tml < Exml. 那就要借位,保证加减都不出现负数
					// (E+1)+tml - Exml = ( E+1) + tml - ( E - aml ) = tml + aml + 1
					if ( tml < Exml )
					{
						tml = tml + aml + 1;
						tmh = tmh - Exmh  - 1;
					}
					else
					{
						tml = tml - Exml;
						tmh = tmh - Exmh;
					}
					
					amh = tmh;
					aml = tml;
					// 如10/3的情况
					if ( ( amh & (U8)0x80 ) == (U8)0x80 )
					{
						// 要特殊处理
						//例如:被除数为x,除数为y, x与y最高位都为1,x<y了, 这时应有 2x-y,(x左移一位),注意x,y都为无符号数,相减后不要产生负数
						// 位数中的最大数为E,如一位10进制数最大数为9,  这时可用公式 差= ( E-y+x) -( E- x) 
						// 但这个处理应在步骤1中处理
						FLAGOVER= 1;

					}
					else
					{
						FLAGOVER = 0;
						// 被除数左移一位
						SL40(&amh,&aml);

					}
					
				
				}
			}
			else
			{
				// 被除数小于除数,商上0
				k=0;
				// 如果被除数最高位已为1了,仍小于除数时,就要进一步左移,(这是相当于原被除数乘2)
				if ( ( amh & (U8)0x80 ) == (U8)0x80 )
				{
					// 要特殊处理
					//例如:被除数为x,除数为y, x与y最高位都为1,x<y了, 这时应有 2x-y,(x左移一位),注意x,y都为无符号数,相减后不要产生负数
					// 位数中的最大数为E,如一位10进制数最大数为9,  这时可用公式 差= ( E-y+x) -( E- x) 
					// 但这个处理应在步骤1中处理
					FLAGOVER= 1;

				}
				else
				{
					// 被除数左移一位
					SL40(&amh,&aml);

				}
			}
			

			
			if ( i < 8 )// 高八位
			{
				mh= mh *2 + k;
			}
			if ( i>=8)
			{
				ml= ml * 2 +k;
			}
		}
		// 得到40位商,并没有除净,程序就会到这了
		ft.mh = mh;
		ft.ml = ml;
		return ( ft );

	}
	return ( ft );
}



⌨️ 快捷键说明

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