📄 myfloat.c
字号:
{
// 规格化处理
// 这时需先左移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 + -