📄 myfloat.c
字号:
// 指数就为-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 + -