大数相乘 - 浮点数

 最多支持0.04G位的大浮点数相乘算法,提供10000阶乘的例子.

昨天,噢不,今日拂晓,鸡鸣之时,写了一大整型数相乘,下午有空,改进了一下,昨天直觉说实现以上几点能提升45%今天一试,哈准.果然是45%左右

2006-11-2 14:12
修改:
1. 对字符串进行封装为bignum
2. 内部由char* 代替string
3. 支持浮点运算.

性能提升50%

提升性能的改进设想:
1. 对于小型的long,int,__int64等,采用非string的处理方式,以减少整型与字串转换.


实现以上1点,性能大约提升5%~10%,乱猜的 :)

如果可能的话会加上除法

//  $Id: multi.cpp 7 2006-11-02 06:30:51Z JiangMiao $ 
//  JiangMiao's Blog  http://blog.csdn.net/antter
#include  " stdafx.h "
#include 
< iostream >
#include 
< string >
using   namespace  std;

#define  SAFE_DELETE(p) if((p)!=NULL){delete p;p=NULL;}
typedef unsigned 
long  DWORD;
#define  OK 0
#define  FAIL (DWORD)-1

class  bignumFunc
    {
    
    
public :
    
///  转换字符串为
    inline  static   char *  strToInt( const   string &   in
        {
        
char *  rt = new   char [ in .size()];
        
for (size_t i = 0 ;i < in .size();i ++
            {
            rt[i]
= in [i] - ' 0 ' ;
            }
        
return  rt;
        }

    };
class  bignum
    {

    
char *  str;
    size_t length;
    size_t point;

    
public :
    bignum():str(NULL),length(
0 ),point( 0 )
        {
        }
    
~ bignum()
        {
        }
    bignum(
const  bignum &  b)
        {
        init(b.length);
        length
= b.length;
        point
= b.point;
        memcpy(str,b.str,length);
        }
    size_t size()
        {
        
return  length;
        }
    DWORD reset()
        {        
        SAFE_DELETE(str);
        length 
=   0 ;
        point 
=   0 ;
        
return  OK;
        }

    
//  分配空间
    DWORD init(size_t length)
        {
        reset();
        str
= new   char [length];
        memset(str,
0 ,length);
        
return  OK;
        }

    
//  读入string
    DWORD read( const   string &   in )
        {
        
return  read( in .c_str(), in .size());
        }
    DWORD read(
const   char *   in ,size_t length)
        {
        init(length);
        
char *  str = this -> str;
        size_t i;
        
for (i = 0 ;i < length;i ++ )
            {
            (
* str ++ ) = ( * in ++ ) - ' 0 ' ;
            
if (( * in ) == ' . '
                {
                i
++ ;
                
break ;
                }
            }
        point
= i;
        
if (i == length) 
            {
            
this -> length = i;
            
return  OK;
            }
        i
++ ;            
        
for (;i < length;i ++ )
            {
            (
* str ++ ) = ( *++ in ) - ' 0 ' ;
            }
        
this -> length = i - 1 ;
        
return  OK;
        }

    
// 输出到string
     string  toString()
        {
        
string  rt;
        rt.reserve(length
+ 1 );
        size_t i;
        
for (i = 0 ;i < point;i ++ )
            {
            rt.append(
1 ,str[i] + ' 0 ' );
            }
        
if (length != point) 
            {
            rt.append(
1 , ' . ' );
            
for (;i < length;i ++ )
                {
                
// 这里可加入小数点后的末尾0不输出
                rt.append( 1 ,str[i] + ' 0 ' );
                }
            }
        
return  rt;
        }

    
    
/* *
     * 大数相乘,最大位数 0.04G 即32位int/(9*9)
     
*/
    
static  bignum *  mul(bignum *  rt,bignum *  sa,bignum *  sb)
        {
        size_t la
= sa -> length;
        size_t lb
= sb -> length;
        size_t xs
= sa -> point + sb -> point; // 小数位数
        size_t lr = la + lb;  // 最大可能位数
         char *  a = sa -> str;
        
char *  b = sb -> str;
        unsigned  
int *  r = new  unsigned  int [lr]; // 分配结果空间
        size_t ia,ib,ir;
        rt
-> init(lr);
        memset(r,
0 ,lr * sizeof ( int ));
        
for (ia = 0 ;ia < la;ia ++ // 相乘
            {
            
for (ib = 0 ;ib < lb;ib ++ )
                {
                ir
= ib + ia + 1 ;
                r[ir]
+= a[ia] * b[ib];
                }
            }
        
for (ir = lr - 1 ;ir > 0 ;ir -- // 进位
            {
            
int  add = r[ir] / 10 ;
            r[ir
- 1 ] += add;
            r[ir]
%= 10 ;
            }
        size_t i
= 0 ;
        
for (ir = 0 ;ir < lr;ir ++ // 除去前面多余的0
            {
            
if (r[ir] != 0 )
                
break ;
            i
++ ;
            }
        xs
-= i;
        i
= 0 ;
        
char *  dr = rt -> str;
        
for (;ir < lr;ir ++ // 生成字串
            {
            dr[i
++ ] = r[ir];
            }
        
// Reserved: 除去尾部多余0,如果放入输出函数可提升效率
        rt -> length = i;
        rt
-> point = xs;
        delete r;
        
return  rt;
        }
    };

class  bignumBuilder
    {
    
public :
        
static  bignum *  build( const   string &  str)
            {
            bignum
*  bn = new  bignum();
            bn
-> read(str);
            
return  bn;
            }
    };

/*

Revision: 6
2006-11-2 5:30
提升性能的改进设想:
1. 使用char* 代替string
2. 多数相乘返回非string,最后由intToStr进行字串输出,可极大地节省预处理和生成的时间

实现以上两点性能提升至少45%,乱猜的 :)
-------------------------------------------
Revision: 7
2006-11-2 14:12
修改:
1. 对字符串进行封装为bignum
2. 内部由char* 代替string
3. 支持浮点运算.

性能提升50%

提升性能的改进设想:
1. 对于小型的long,int,__int64等,采用非string的处理方式,以减少整型与字串转换.


实现以上1点,性能大约提升5%~10%,乱猜的 :)
-------------------------------------------
*/


///  以下为测试文件
#include  " windows.h "
int  main( int  argc, char **  argv)
    {
    
string  rt;
    bignum
*  an = new  bignum();
    bignum
*  bn = new  bignum();
    bignum
*  cn = new  bignum();
    LARGE_INTEGER fre,begin,end;
    QueryPerformanceFrequency(
& fre);
    QueryPerformanceCounter(
& begin);

/*     10000阶乘测试
    cn->read("1");
    for(int i=1;i<=10000;i++)
        {
        bignum* tmp=an;
        an=cn;
        cn=tmp;
        char b[6];
        _itoa_s(i,b,10);
        bn->read(b);
        bignum::mul(cn,an,bn);
        }
*/
    
/*
    浮点数相乘
*/
    an
-> read( " 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989 " );
    bignum::mul(cn,an,an);

    QueryPerformanceCounter(
& end);
    cout
<< " Spend  " << (end.QuadPart - begin.QuadPart) * 1000000 / fre.QuadPart << " ns " << endl;
    cout
<< cn -> size() << endl;
    
// cout<<cn->toString()<<endl;
     return   0 ;
    }


/*  测试10000!的结果
 * C4 2.66MHZ

revision: 6
Spend 16911238ns //17s
35660.

------------------------
revision: 7
10000阶乘
Spend 8441291ns (8.5秒)提升50%
35660

//1000位大浮点数相乘
Spend 3147ns
2001
请按任意键继续. . .
 
*/

 

 欢迎探讨.

我的Blog是 http://blog.csdn.net/antter
Email: jmiwork@yahoo.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值