大数相乘(支持浮点数)

来源:互联网 发布:韩顺平数据库视频教程 编辑:程序博客网 时间:2024/05/19 14:36
// $Id: multi.cpp 7 2006-11-02 06:30:51Z JiangMiao $ // JiangMiao's Blog http://blog.csdn.net/antter#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)-1class 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;}// 读入stringDWORD 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;}//输出到stringstring 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: 62006-11-2 5:30提升性能的改进设想:1. 使用char* 代替string2. 多数相乘返回非string,最后由intToStr进行字串输出,可极大地节省预处理和生成的时间实现以上两点性能提升至少45%,乱猜的 :)-------------------------------------------Revision: 72006-11-2 14:12修改:1. 对字符串进行封装为bignum2. 内部由char* 代替string3. 支持浮点运算.性能提升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;system("pause");return 0;}/* 测试10000!的结果* C4 2.66MHZrevision: 6Spend 16911238ns //17s35660.------------------------revision: 710000阶乘Spend 8441291ns (8.5秒)提升50%35660//1000位大浮点数相乘Spend 3147ns2001请按任意键继续. . .*/


http://blog.csdn.net/antter/article/details/1362761

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>using namespace std;#define N 100//将在数组中保存的字符串转成数字存到int数组中void getdigits(int *a,char *s){     int i;     char digit;     int len = strlen(s);     for(i = 0; i < len; ++i) {           digit = *(s + i);           *(a + len - 1 - i) = digit - '0';//字符串s="12345",因此第一个字符应该存在int数组的最后一个位置     }}//将数组a与数组b逐位相乘以后存入数组cvoid multiply(int *a,int *b,int *c){ /*  数组a中的每位逐位与数组b相乘,并把结果存入数组c  比如,12345*12345,a中的5与12345逐位相乘  对于数组c:*(c+i+j)在i=0,j=0,1,2,3,4时存的是5与各位相乘的结果  而在i=1,j=0,1,2,3,4时不光会存4与各位相乘的结果,还会累加上上次相乘的结果.这一点是需要注意的!!! */for(int i = 0; i < N; ++i)for(int j = 0; j < N; ++j)*(c + i + j) += *(a + i) * *(b + j);  //这里是移位、进位for(int i = 0; i < 2 * N - 1; ++i){*(c + i + 1) += *(c + i)/10; //将十位上的数向前进位,并加上原来这个位上的数*(c + i) = *(c + i)%10;//将剩余的数存原来的位置上}}int main(){int a[N] = {0},b[N]= {0},c[2*N] = {0};char s1[N] = "99999999999999999999999999999999999999999999999";      getdigits(a,s1);getdigits(b,s1);    multiply(a,b,c);    int j = 2*N-1;while(c[j] == 0)j--;for(int i = j;i >= 0; --i)printf("%d",c[i]);    printf("\n");system("pause");    return 0;}

 

0 0
原创粉丝点击