📄 myfloat.c
字号:
//#include "reg51.h"
// myfloat.cpp : Defines the entry point for the console application.
//
// 自定义32位浮点类型及运算
// 2005.12.25
// 邓彬伟 于黄石理工
////////////////////////////////////////////////////////////////////////
#include "reg52.h"
#include "myfloat.h"
char FLAGOVER;
char FLAGALEB;
xdata myfloat ft;
int main()
{
xdata U32 lt;
xdata long i,j;
// printf( "%d.....",MyfloatToLong(MyfloatDiv( LongToMyfloat( 3), LongToMyfloat( 1 ))));
SP= 0x79;
ft=MyfloatMul( LongToMyfloat( 3), LongToMyfloat( 3 ));
ft=MyfloatAdd( LongToMyfloat( 4 ) , LongToMyfloat( 3 ));
ft=MyfloatSub( LongToMyfloat( 454 ) , LongToMyfloat(33));
ft=MyfloatDiv( LongToMyfloat( 454 ) , LongToMyfloat(33));
// 例子,32位有符号整数转myfloat
LongToMyfloat( 0x7fffffff );//
LongToMyfloat( 0xffffffff );
LongToMyfloat( 0 );
// 例子,32位有符号整数转myfloat
ShortToMyfloat( (short)0x7fff );//
ShortToMyfloat( (short)0xffff);
ShortToMyfloat( 0 );
// 例子,myfloat转32位有符号整数
// printf(" short= %d \n ", (short)0xf432);
// printf(" long = %d \n ", MyfloatToLong(LongToMyfloat( (long)(short)0xf432 ) ) );
// printf(" add = %d ,long add = %d \n ",0x7fffffff+0x7fffffff, MyfloatToLong(MyfloatAddp( LongToMyfloat( 0x7fffffff ) , LongToMyfloat( 0x7fffffff ))) );
MyfloatToLong(ShortToMyfloat( (short)-0x7e ) );//
// 测试MyfloatSubp()函数
// printf(" sub = %d ,long sub = %d \n ",0x7fffffff-0x7fffffff, MyfloatToLong(MyfloatSubp( LongToMyfloat( 0x7fffffff ) , LongToMyfloat( 0x7fffffff ))) );
// printf(" sub = %d ,long sub = %d \n ",0x7fffffff-0x7ffffff, MyfloatToLong(MyfloatSubp( LongToMyfloat( 0x7fffffff ) , LongToMyfloat( 0x7ffffff ))) );
// printf(" sub = %d ,long sub = %d \n ",0x7fff-0x7ffffff, MyfloatToLong(MyfloatSubp( LongToMyfloat( 0x7fff ) , LongToMyfloat( 0x7ffffff ))) );
// printf(" sub = %d ,long sub = %d \n ",0x0-0x7ffffff, MyfloatToLong(MyfloatSubp( LongToMyfloat( 0x0 ) , LongToMyfloat( 0x7ffffff ))) );
// printf(" sub = %d ,long sub = %d \n ",0x0-0x0, MyfloatToLong(MyfloatSubp( LongToMyfloat( 0x0 ) , LongToMyfloat( 0x0 ))) );
// printf(" sub = %d ,long sub = %d \n ",0x7fffffff-0x0, MyfloatToLong(MyfloatSubp( LongToMyfloat( 0x7fffffff ) , LongToMyfloat( 0x0 ))) );
// printf(" sub = %d ,long sub = %d \n ",0x1-0x2, MyfloatToLong(MyfloatSubp( LongToMyfloat( 0x1) , LongToMyfloat( 0x2 ))) );
// 测试MyfloatAdd()函数
lt =((S32)0x8fffffff+0x7ffffff);//
// printf(" adds = %d ,long add = %d \n ",0x7fffffff-0x7fffffff, MyfloatToLong(MyfloatAdd( LongToMyfloat( 0x7fffffff ) , LongToMyfloat( -0x7fffffff ))) );
// printf(" adds = %d ,long add = %d \n ",lt, MyfloatToLong(MyfloatAdd( LongToMyfloat( 0x8fffffff ) , LongToMyfloat( 0x7ffffff ))) );
// printf(" adds = %d ,long add = %d \n ",0x7fff+0x7ffffff, MyfloatToLong(MyfloatAdd( LongToMyfloat( 0x7fff ) , LongToMyfloat( 0x7ffffff ))) );
// printf(" adds = %d ,long add = %d \n ",0x80123456+0x8fffffff, MyfloatToLong(MyfloatAdd( LongToMyfloat( 0x80123456 ) , LongToMyfloat( 0x8fffffff ))) );
// printf(" adds = %d ,long add = %d \n ",0x0+0x0, MyfloatToLong(MyfloatAdd( LongToMyfloat( 0x0 ) , LongToMyfloat( 0x0 ))) );
// printf(" adds = %d ,long add = %d \n ",0x7fffffff+0x7fffffff, MyfloatToLong(MyfloatAdd( LongToMyfloat( 0x7fffffff ) , LongToMyfloat( 0x7fffffff ))) );
// printf(" adds = %d ,long add = %d \n ",0x1+0x2, MyfloatToLong(MyfloatAdd( LongToMyfloat( 0x1) , LongToMyfloat( 0x2 ))) );
// 测试MyfloatSub()函数
// printf(" subs = %d ,long sub = %d \n ",0x7fffffff-0x7fffffff, MyfloatToLong(MyfloatSub( LongToMyfloat( 0x7fffffff ) , LongToMyfloat( 0x7fffffff ))) );
// printf(" subs = %d ,long sub = %d \n ",0x7ffffff-0xffffffff, MyfloatToLong(MyfloatSub( LongToMyfloat( 0x7ffffff ) , LongToMyfloat( 0xffffffff ))) );
// printf(" subs = %d ,long sub = %d \n ",0xffffffff-0x7ffdffff, MyfloatToLong(MyfloatSub( LongToMyfloat( 0xffffffff ) , LongToMyfloat( 0x7ffdffff ))) );
// printf(" subs = %d ,long sub = %d \n ",0x83f1feff-0xffffffff, MyfloatToLong(MyfloatSub( LongToMyfloat( 0x83f1feff ) , LongToMyfloat( 0xffffffff ))) );
// 测试MyfloatMul()函数
// printf(" muls = %d ,long mul = %d \n ",0x7fffffff*0x7fffffff, MyfloatToLong(MyfloatMul( LongToMyfloat( 0x7fffffff ) , LongToMyfloat( 0x7fffffff ))) );// myfloat=0x3dfffffff800 64位整数为0x3fffffff00000001 ,myfloat达不到这高所以转化为32位的积为0是正确
// printf(" muls = %d ,long mul = %d \n ",0xf3f1feff*0x2, MyfloatToLong(MyfloatMul( LongToMyfloat( 0xf3f1feff ) , LongToMyfloat( 0x2 ))) );
// printf(" muls = %d ,long mul = %d \n ",0*0x2, MyfloatToLong(MyfloatMul( LongToMyfloat( 0 ) , LongToMyfloat( 0x2 ))) );
// printf(" muls = %d ,long mul = %d \n ",(3)*(4), MyfloatToLong(MyfloatMul( LongToMyfloat( 3) , LongToMyfloat( 4 ))) );
// 测试MyfloatDiv()函数 全部通过!运行时间20分钟i=0--9999,j=1--9999 ,1亿次
for ( i =-100; i<100; i++)
for ( j =1; j<1000;j++)
{
// MyfloatAdd( LongToMyfloat( i ) , LongToMyfloat( j ));
//printf(" i=%d, j=%d div = %d, long div =%d \n ", 385,3,(unsigned long )(385/3), MyfloatToLong(MyfloatDiv( LongToMyfloat( 385), LongToMyfloat( 3 ))));
// printf(" i=%d,j=%d, adds = %d ,long add = %d \n ",i,j,i-j, MyfloatToLong(MyfloatSub( LongToMyfloat( i ) , LongToMyfloat( j ))) );
// printf(" i=%d,j=%d, muls = %d ,long Mul= %d \n ",i,j,i*j, MyfloatToLong(MyfloatMul( LongToMyfloat( i ) , LongToMyfloat( j ))) );
if ((unsigned long )(i*j) != MyfloatToLong(MyfloatMul( LongToMyfloat( i ) , LongToMyfloat( j ))) )//(unsigned long )(i-j) != MyfloatToLong(MyfloatSub( LongToMyfloat( i ) , LongToMyfloat( j ))) ) // MyfloatToLong(MyfloatDiv( LongToMyfloat( i), LongToMyfloat( j ))) )
{
// if ( i*j %20 == 0 ) getchar();
// 除法测试通过
/// printf(" i=%d, j=%d div = %d, long div =%d \n ", i,j,(unsigned long )(i/j), MyfloatToLong(MyfloatDiv( LongToMyfloat( i), LongToMyfloat( j ))));
// 加法测试1 亿次3分钟通过
// printf(" i=%d,j=%d, adds = %d ,long add = %d \n ",i,j,i+j, MyfloatToLong(MyfloatAdd( LongToMyfloat( i ) , LongToMyfloat( j ))) );
// 减法测试通过
// printf(" i=%d,j=%d, subs = %d ,long Sub= %d \n ",i,j,i-j, MyfloatToLong(MyfloatSub( LongToMyfloat( i ) , LongToMyfloat( j ))) );
// 乘法测试通过
// printf(" i=%d,j=%d, muls = %d ,long Mul= %d \n ",i,j,i*j, MyfloatToLong(MyfloatMul( LongToMyfloat( i ) , LongToMyfloat( j ))) );
}
}
// 精度测试
// printf(" div = %f, long div =%d \n ", ((double)1/(double)355.0 )*1000000000, MyfloatToLong(MyfloatDiv( MyfloatMul(LongToMyfloat(100000000), MyfloatMul( LongToMyfloat(1000000000),MyfloatDiv( LongToMyfloat( 1 ), LongToMyfloat( 355 ))) ),LongToMyfloat(1000000)) ) );
return 0;
}
//////////////////////////////////////////////////////////////////////////////
// 算法实现
//////////////////////////////////////////////////////////////////////////////
// 32位有符号型整数----> myfloat类型转化
myfloat LongToMyfloat( S32 ivar )
{
xdata myfloat ft;
xdata U32 fet; // 计算指数的变量
xdata U32 fmt;// 临时存放尾数m的位的变量
xdata char e; // 存放指数值
fmt = (U32)( ivar & BIT_S32V );// 默认为正整数,直接取真值
ft.s = 0; // 默认为正整数
if ( BIT_S32S ==( ivar & BIT_S32S ) ) // 如果32位符号整数最高位为1
{
// 求补码的真值
fmt = (U32)( ( ~( ivar & BIT_S32V ) + 1 ) & BIT_S32V ) ;
// 送符号到myfloat中
ft.s = 1;
}
if ( 0 ==fmt )// 如果整数为0
{
ft.s = 0;
ft.e = 0;
ft.mh = 0;
ft.ml=0;
return ( ft );
}
// 计算指数e
e = 1;
fet = fmt;
while ( fet = ( fet / 2 ) )
{
e++;
}
ft.e = e;
// 计算尾数,因为此时fmt中的真值的二进制即是我们的尾数中的数,但还未规格化,即要求尾数>=0.1
// 这个尾数已有的位数即是指数e的值,剩余位要补0
// 如果,指数e>40 则尾数只取40位,剩下的则要舍去,则出现舍入误差
// if ( e > 40 )
// {
// e =40;
// }
if ( e > 8 )
{
ft.mh = (U8) ( fmt >> ( e - 8 ) );// 得到高8位,
ft.ml = fmt << ( 32 -( e - 8 ) ); // 低32位,高位对齐
}
else
{
ft.mh = (U8)(((U8) fmt) << ( 8 - e )); //高位对齐
ft.ml = 0;
}
return (ft);
}
// 16位有符号整型----> myfloat类型转化
myfloat ShortToMyfloat( S16 ivar )
{
myfloat ft;
U32 fet; // 计算指数的变量
U32 fmt;// 临时存放尾数m的低32位的变量
S8 e; // 存放指数值
fmt = (U32)( ivar & BIT_S16V );// 默认为正整数,直接取真值
ft.s = 0; // 默认为正整数
if ( BIT_S16S==( ivar & BIT_S16S ) ) // 如果32位符号整数最高位为1
{
// 求补码的真值
fmt = (U32)( ( ~( ivar & BIT_S16V ) + 1 ) & BIT_S16V ) ;
// 送符号到myfloat中
ft.s = 1;
}
if (0 ==fmt )// 如果整数为0
{
ft.s = 0;
ft.e = 0;
ft.mh = 0;
ft.ml=0;
return ( ft );
}
// 计算指数e
e = 1;
fet = fmt;
while ( fet = ( fet / 2 ) )
{
e++;
}
ft.e = e;
// 计算尾数,因为此时fmt中的真值的二进制即是我们的尾数中的数,但还未规格化,即要求尾数>=0.1
// 这个尾数已有的位数即是指数e的值,剩余位要补0
// 如果,指数e>40 则尾数只取40位,剩下的则要舍去,则出现舍入误差
// if ( e > 40 )
// {
// e =40;
// }
if ( e > 8 )
{
ft.mh = (U8)( (U8) ( fmt >> ( e - 8 ) ) );// 得到高8位,
ft.ml = fmt << ( 32 -( e - 8 ) ); // 低32位,高位对齐
}
else
{
ft.mh = (U8) ( ((U8) fmt) << ( 8 - e ) ); //高位对齐
ft.ml = 0;
}
return (ft);
}
// myfloat类型转化---->32位有符号型整数
// myfloat类型转化为32位有符号型整数时:
// 当myfloat值大于32位有符号型整数范围时:
// 采用的是截断高位的方法,但符号位仍保留
// 这样负数仍是负数,正数仍是正数
// 如有一个myfloat 数:0x90efedcbab00
// 这是一个负数 N= - (0x0.efedcbab00)* 2^32= -4025338795;它超出了S32的范围
// 转成S32时,结果是: -1877855147= -((0xefedcbab) &0x7fffffff);//即截去最高位
// 对于正数也是类似处理.
// 若是ANSI中对超出范围的数-4025338795的处理是: -4025338795 =0xefedcbab
// 对0xefedcbab求补码, ~0xefedcbab+1=0x10123455 =269628501 ;这样就成了正数了
// 这有别于ANSI中的有符号数超出范围就成为相应的补码形式
// 也不同于float 类型超出整数范围时转为有符号数整数的形式
S32 MyfloatToLong( myfloat fvar )
{
xdata myfloat ft;
xdata S32 it;
xdata S32 imt;
xdata U32 imtv;//真值
xdata U8 ftmh,i;
xdata U32 ftml;
ft = fvar;
ftmh = ft.mh;
ftml = ft.ml;
it = ( (S32)ft.s )<< 31;// 得到符号位
// 是纯小数时:
if ( ( ( ft.e & BIT_MASKES ) == BIT_MASKES ) ) // 指数符号位为1,即是负指数,纯小数是小于0.5的
{
return ( (S32)0 );
}
if ( (0==ft.e ) )// 即纯小数可能大于0.5
{// 不四舍五入
/* if ( 0x80 == ( ft.mh & 0x80 ) ) // 得到最高位,为1说明纯小数大于0.5
{
return ( (S32)1 );
}
else
*/ {
return ( (S32)0 );
}
}
if ( ft.e >31 )// >31就要截断高于31位的数
{
/* 有错的代码
if ( 39 == ft.e )
{
imt = (S32)( ( ft.ml >> 1 ) & BIT_MASKSNOT );// 得到真值
}
if ( 40 == ft.e )
{
imt = (S32) (ft.ml &BIT_MASKSNOT );// 截去第31位(31~0)
}
if ( ft.e < 39 )
{
iet =ft.e -31; // 得到ft.mh中可截断的高位位数
// ft.mh << iet 位,实现要取的在于ft高8位的数移到8位的最高位,
// 再移23位,就移到32位符号整数的高31位了, 再把ft.ml部分的位数,移到32位的最低位边,
// 最后高位和低位按位或,就可以得到要求的真值了.
// ft.mh<< iet 是按32位的中间结果的,但我要去掉iet位,所以必须(unsigned char)(ft.mh << iet )
imt = (S32)( (((U32)( (unsigned char)(ft.mh << iet )) )<< 23) |((U32)( ( ft.ml >> ( 40 - ft.e ) ))) );
}
*/
for ( i = 1 ; i<= (ft.e -31); i++ )
{
SL40(&ftmh,&ftml);
}
imtv = (U32)((((U32)ftmh)<< 23) | (ftml >> 9) );// 组成31位的真值,放在低31位,最高位这里为0
}
if ( ft.e <= 31 )
{
if ( ft.e >= 8)
{// 高8位和低32位中的数拼成31位的整数真值
if ( ft.e == 8 )
{
imtv= (S32)( ((U32)ft.mh )<< ( ft.e -8 ) );
}
else
{
imtv = (S32) ( ( ((U32)ft.mh )<< ( ft.e -8 ) ) | (ft.ml >> ( 40- ft.e) ) );
}
}
if ( ft.e < 8 )
{
imtv = (U32) ( ((U32)ft.mh ) >> ( 8 - ft.e )); // 右对齐
imtv = imtv & (~0x80000000);
}
}
// 是负数真值以补码表示
if (1 ==ft.s )
{
imt = (S32)( it | ( ( ( ~imtv ) + 1 ) & BIT_MASKSNOT ) ); // it是符号位的符号
}
else
{
imt = (S32) (it |imtv);
}
return ( imt );
}
// myfloat类型任意数相加
// 负数 - 正数 +
// -- -+ +- ++ 四种相加
myfloat MyfloatAdd( myfloat a, myfloat b )
{
xdata myfloat ft;
xdata myfloat ft1,ft2;
ft1=a;
ft2=b;
if ((0==ft1.s ) && ( 0==ft2.s)) //两个都是正数
{
ft=MyfloatAddp(ft1,ft2);
return ( ft );
}
if ((0==ft1.s ) && (1==ft2.s ) )//ft1为正,ft2为负
{
ft2.s = 0;// ft2变为正数,调用两正数相减函数
ft =MyfloatSubp(ft1,ft2);
return (ft );
}
if ((1==ft1.s) && (0==ft2.s )) // ft1为负,ft2为正
{
ft1.s =0;// ft1变为正数,调用两正数相减函数
ft= MyfloatSubp(ft2,ft1);
return (ft);
}
if ( (1==ft1.s) && (1==ft2.s) ) //ft1,ft2都为负
{
ft1.s =0;
ft2.s = 0;
ft= MyfloatAddp(ft1,ft2);
ft.s =1;
return ( ft );
}
return ( *(myfloat *)0 ); // 不可能到达这!
}
// myfloat类型任意数相减
// 负数 -,正数 +
// -- -+ +- ++ 四种相减
myfloat MyfloatSub( myfloat a, myfloat b )
{
xdata myfloat ft;
xdata myfloat ft1,ft2;
ft1=a;
ft2=b;
if ((0==ft1.s ) && ( 0==ft2.s)) //两个都是正数
{
ft =MyfloatSubp(ft1,ft2);
return ( ft );
}
if ((0==ft1.s ) && (1==ft2.s ) )//ft1为正,ft2为负
{
ft2.s = 0;// ft2变为正数,调用两正数相加函数
ft=MyfloatAddp(ft1,ft2);
return (ft );
}
if ((1==ft1.s) && (0==ft2.s )) // ft1为负,ft2为正
{
ft1.s =0;
ft= MyfloatAddp(ft1,ft2);
ft.s =1;
return ( ft );
}
if ( (1==ft1.s) && (1==ft2.s) ) //ft1,ft2都为负
{
ft1.s =0;// ft1变为正数,调用两正数相减函数
ft2.s = 0;
ft= MyfloatSubp(ft2,ft1);
return ( ft);
}
return ( *(myfloat *)0 ); // 不可能到达这!
}
// 这个是被上两函数调用的子函数// 正数+正数
myfloat MyfloatAddp( myfloat a, myfloat b )
{
xdata myfloat ft;
xdata myfloat ft1, ft2;
xdata S8 fet;
xdata U32 fmt2ml,fmt2mh,fmtmladd;
xdata U8 fmtmhadd,fmtmhaddt;
xdata U8 fmtmhC,fmtmlC;
xdata S8 fet1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -