大整数运算Word文件下载.docx

上传人:b****4 文档编号:6819883 上传时间:2023-05-07 格式:DOCX 页数:30 大小:202.24KB
下载 相关 举报
大整数运算Word文件下载.docx_第1页
第1页 / 共30页
大整数运算Word文件下载.docx_第2页
第2页 / 共30页
大整数运算Word文件下载.docx_第3页
第3页 / 共30页
大整数运算Word文件下载.docx_第4页
第4页 / 共30页
大整数运算Word文件下载.docx_第5页
第5页 / 共30页
大整数运算Word文件下载.docx_第6页
第6页 / 共30页
大整数运算Word文件下载.docx_第7页
第7页 / 共30页
大整数运算Word文件下载.docx_第8页
第8页 / 共30页
大整数运算Word文件下载.docx_第9页
第9页 / 共30页
大整数运算Word文件下载.docx_第10页
第10页 / 共30页
大整数运算Word文件下载.docx_第11页
第11页 / 共30页
大整数运算Word文件下载.docx_第12页
第12页 / 共30页
大整数运算Word文件下载.docx_第13页
第13页 / 共30页
大整数运算Word文件下载.docx_第14页
第14页 / 共30页
大整数运算Word文件下载.docx_第15页
第15页 / 共30页
大整数运算Word文件下载.docx_第16页
第16页 / 共30页
大整数运算Word文件下载.docx_第17页
第17页 / 共30页
大整数运算Word文件下载.docx_第18页
第18页 / 共30页
大整数运算Word文件下载.docx_第19页
第19页 / 共30页
大整数运算Word文件下载.docx_第20页
第20页 / 共30页
亲,该文档总共30页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

大整数运算Word文件下载.docx

《大整数运算Word文件下载.docx》由会员分享,可在线阅读,更多相关《大整数运算Word文件下载.docx(30页珍藏版)》请在冰点文库上搜索。

大整数运算Word文件下载.docx

6.intmenu()/////菜单函数/////

7.intcompare(orderstackinteger1,orderstackinteger2)/////比较大小函数/////按位比较/////

8.intconvert(charx)/////类型转换函数-将字符型转换成整型/////

2.用户界面流程

Y

N

三、详细设计

1、大整数的表示

在32位字长的系统里,基本数据类型有:

8位数,BYTE,单字节:

char,unsignedchar。

16位数,WORD,字:

short,unsignedshort。

32位数,DWORD,双字:

int,unsignedint。

64位数,QWORD,四字:

__int64,unsigned__int64

这些基本数据类型的运算可以被机器指令所直接支持。

在x86平台上,多个字节的数据存放顺序是,低位数据存放在低位地址。

比如,0x00010203,在内存中的存放顺序是03,02,01,00。

照此类推,128位整数,8字,16字节,0x000102030405060708090A0B0C0D0E0F

的内存映像是:

0F,0E,0D,0C,0B,0A,09,08,07,06,05,04,03,02,01,00。

位数是2的整数次方,64位,128位,256位等整数,我们称之为规范整数。

进行大整数的四则运算的时候,一个基本的原理就是把大整数运算降解为32位四则运算的复合运算。

降解的方式可以是位数减半,即256位降解为128位,128位降解为64位,直到降解为机器指令支持范围内的整数。

这样的降解过程用到的所有的中间变量都是规范的整数。

也可以是从高到低,每次降解32位。

这样的话在降解过程中我们会使用到256-32=224,224-32=192,192-32=160等长度不等于2的整数次方的整数,我们称之为不规范的整数。

减半降解运算过程比较容易理解,而逐次降解则会获得较好的性能。

大整数的符号。

一般来说,大整数运算中,负数的使用是非常少的。

如果要使用符号的话,同基本数据一样,最高位表示符号,剩余的数位用来表示有效值。

2、大整数加法

1.2.0在大整数四则运算中,加法是基本的运算,也最容易实现。

只要处理好进位数据就可以了。

LX_RESULT

large_int_add_c32(BYTE*psa,BYTE*psb,BYTE*psd,DWORD*pca,intnBytes)

返回值:

LX_OK

输入参数:

psa,存放第一个操作数的地址。

psb,第二个操作数的地址。

输出参数:

psd,存放运算结果的地址。

pca,存放进位数据的32位无符号整数地址。

nBytes,大整数字节数。

******************************************************************************/

{

inti;

DWORDdwA;

DWORDdwB;

DWORDdwC=0;

DWORD*pwa=(DWORD*)psa;

DWORD*pwb=(DWORD*)psb;

DWORD*pwd=(DWORD*)psd;

for(i=0;

i<

nBytes;

i+=4){

ULARGE_INTEGERuld;

dwA=*pwa++;

//取第一个操作数DWORD;

dwB=*pwb++;

//取第二个操作数DWORD;

uld.QuadPart=(__int64)dwA+dwB+dwC;

//带进位加;

*pwd++=(DWORD)(uld.LowPart);

//低32位输出;

dwC=(DWORD)(uld.HighPart);

//高32位为进位;

}

*pca=dwC;

//输出进位;

returnLX_OK;

}

3、大整数减法

减法在大整数运算里面需要加以注意。

减法是通过把操作数取反并加1,然后做加法实现的。

在使用中应当避免小减大的情况。

如果出现了这种情况,判断结果的最高位,如果是1,

结果清零,或者当作负数继续使用。

voidlarge_int_not(BYTE*psa,intnBytes)

大整数取反运算。

for(inti=0;

nBytes;

DWORD*ps=(DWORD*)(psa+i);

*ps=~*ps;

intlarge_int_reverse(BYTE*psa,intnBytes)

大整数取反并加1。

相当于改变符号。

DWORDdwCarry;

large_int_not(psa,nBytes);

returnlarge_int_add_pass_c32(psa,1,psa,&

dwCarry,nBytes);

//LX_RESULTlarge_int_sub_c32(

//BYTE*psa,BYTE*psb,BYTE*psd,DWORD*pca,intnBytes)

*****************************************************************************/

LX_RESULTlarge_int_sub_c32(BYTE*psa,BYTE*psb,BYTE*psd,DWORD*pca,intnBytes)

BYTE*tmp=(BYTE*)xlivAlloc(nBytes,TRUE);

if(!

tmp){

returnLX_FAIL;

memcpy(tmp,psb,nBytes);

large_int_reverse(tmp,nBytes);

if(LX_OK!

=large_int_add_c32(psa,tmp,psd,pca,nBytes)){

if(tmp){

xlivFree(tmp);

4、大整数乘法

减半降解法。

设A,B是2n位的整数,A1,A0,B1,B0分别是A,B的高低n位。

A=A1<

<

n+A0;

B=B1<

n+B0;

A和B的乘积可以表示为:

A*B=A0*B0+A1*B0<

n+A0*B1<

n+A1*B1<

2n;

这样我们就把2n位的运算降解为多个n位的乘法运算。

我们首先实现一个递归调用的函数,在降解到32位的时候不再降解直接返回结果。

intlarge_int_mul_half_i(BYTE*psa,BYTE*psb,BYTE*psd,intnBytes)

psd=psa*psb;

if(4==nBytes){

*(QWORD*)psd=(QWORD)*(DWORD*)psa**(DWORD*)psb;

returnLX_OK;

DWORDdwCarry=0;

LX_RESULTnRe=LX_OK;

constintnDoubleSize=nBytes*2;

constintnHalfSize=nBytes>

>

1;

BYTE*psa0=(BYTE*)xlivAlloc(nDoubleSize,TRUE);

BYTE*psb0=(BYTE*)xlivAlloc(nDoubleSize,TRUE);

BYTE*psd0=(BYTE*)xlivAlloc(nDoubleSize,TRUE);

BYTE*psa1=(BYTE*)xlivAlloc(nDoubleSize,TRUE);

BYTE*psb1=(BYTE*)xlivAlloc(nDoubleSize,TRUE);

BYTE*psd1=(BYTE*)xlivAlloc(nDoubleSize,TRUE);

BYTE*psdd=(BYTE*)xlivAlloc(nDoubleSize,TRUE);

psa0||!

psb0||!

psd0||!

psa1||!

psb1||!

psd1||!

psdd){

nRe=LX_FAIL;

gotofail;

memcpy(psa0,psa,nHalfSize);

memcpy(psa1,psa+nHalfSize,nHalfSize);

memcpy(psb0,psb,nHalfSize);

memcpy(psb1,psb+nHalfSize,nHalfSize);

large_int_mul_half_i(psa0,psb0,psd0,nHalfSize);

large_int_mul_half_i(psa1,psb0,psd1,nHalfSize);

large_int_shift_c32(psd1,-nHalfSize*8,psd1,nDoubleSize);

large_int_add_c32(psd1,psd0,psdd,&

dwCarry,nDoubleSize);

//dwCarrymustbezero;

large_int_mul_half_i(psa0,psb1,psd0,nHalfSize);

large_int_mul_half_i(psa1,psb1,psd1,nHalfSize);

large_int_add_c32(psd1,psd0,psd1,&

large_int_add_c32(psd1,psdd,psd,&

fail:

if(psa0){xlivFree(psa0);

if(psb0){xlivFree(psb0);

if(psd0){xlivFree(psd0);

if(psa1){xlivFree(psa1);

if(psb1){xlivFree(psb1);

if(psd1){xlivFree(psd1);

if(psdd){xlivFree(psdd);

returnnRe;

然后我们用一个看来很简单的实现来调用上面的递归函数。

intlarge_int_mul_half(BYTE*psa,BYTE*psb,BYTE*psd,BYTE*pca,intnBytes)

BYTE*tmp=(BYTE*)xlivAlloc(nBytes*2,TRUE);

nRe=large_int_mul_half_i(psa,psb,tmp,nBytes);

if(LX_OK==nRe){

memcpy(psd,tmp,nBytes);

memcpy(pca,tmp+nBytes,nBytes);

减半降解法的思路看来很清晰明了,结果也是正确的。

但是很不幸,同后面我们使用的逐次降解法相比,计算速度低了一个数量级以上:

//减半降解benchmark:

83

//逐次降解benchmark:

5072

大整数乘大整数

intlarge_int_mul_c32(BYTE*psa,BYTE*psb,BYTE*psd,BYTE*pca,intnBytes)

psb,存放第二个操作数的地址。

pca,存放高nBytes字节的内存地址。

constintnpass=nBytes>

2;

constintnpit=nBytes*2;

constintnsize=npit*npass;

BYTE*tmp=(BYTE*)xlivAlloc(nsize*2,TRUE,nBytes*2);

BYTE*p=tmp;

npass;

i++){

if(LX_OK!

=large_int_mul_pass_c32(psa,*pwb++,p,&

dwCarry,nBytes)){

gotofail;

}

p+=npit;

p=tmp;

npass;

memcpy(p+nsize+i*4,p,npit-i*4);

p=tmp+nsize;

npass-1;

large_int_add_c32(p,p+npit,p+npit,&

dwCarry,npit);

memcpy(psd,p,nBytes);

memcpy(pca,p+nBytes,nBytes);

returnLX_FAIL;

四调试分析

序号

时间

问题与解决方法

1

3月15日

复习数据结构和C++教科书

2

3月19日

上网找相关资料,用数组存放大整数

3

3月24日

开始尝试编写程序

4

3月27日

大概编写顺序栈classorderstack

5

3月31日

编写大整数的加法运算函数

6

4月4日

编写“类型转换函数”-将字符型转换成整型

7

4月5日

减法是加法的逆运算思路,编写大整数数的减法函数。

8

4月12日

查找资料开始编写乘法函数,并优化

9

4月15日

解决异号运算时出现的错误

10

4月17日

搜寻资料

11

4月19日

编写主函数,输入函数,把各个函数之间联系起来

12

完善程序

13

反复调试程序,测试数据,不断改进程序。

14

4月20日

撰写数据结构大整数设计报告。

五、用户使用说明

配程序界面图解释:

运行程序你会看到如下的界面:

此时选择需要的运算功能,例如键入“1”,在敲击“Enter”,则界面变成

此时可输入a的值,如1234567890123456789012345,再敲击“Enter”,程序出现

,此时可输入b的值,如9876543210987654321098765,并敲击“Enter”,则界面变成

此时可选择继续运算或退出程序。

六、测试结果

(一)长整数运算:

a:

1234567890123456789012345b:

9876543210987654321098765

加法结果:

111111*********11110111110

运算时间:

3.553821ms

减法结果:

--8641975320864197532086420

3.521396ms

乘法结果:

12193263113702179522618496034720321071359549253925

9.687679ms

(二)普通短整数运算:

数A:

123数B:

987

1110运行时间:

0.550890ms

-864运行时间:

0.852275ms

121401运行时间:

0.614036ms

注:

以上结果测试环境:

操作系统Win7旗舰版、CPUADMX3、主板磐正AK785+DDR3、内存金士顿2GDDR1333、硬盘西数500G、显卡铭鑫9800G7N

八、心得小记

这一次的数据结构课程设计,我付出了艰辛的努力,因为一直就觉得自己不擅长做编程一类的工作,这一次更坚定了我的想法。

我曾经尝试想把除法运算也完成,但无奈才疏学浅,多番努力之下还是没有实现。

不过能做到现在这样,我自己也算是比较满意的了。

总的来说,这是一次不错的经历,让我再一次亲近了代码,并深知程序开发的艰辛,不由得对那些奋斗在软件开发行业的人们肃然起敬。

七、附录

源程序代码(不打印)

#include<

Windows.h>

iostream>

usingnamespacestd;

#include"

stdio.h"

////////////////////////////////////////////////////////////和计时器相关的代码块

_LARGE_INTEGERTimeStart;

_LARGE_INTEGERTimeEnd;

voidStartCount()

QueryPerformanceCounter(&

TimeStart);

}//计时开始

voidEndCount()

TimeEnd);

}//计时结束

doubleTime()

doubleFreq;

//计时器频率

LARGE_INTEGERd;

if(QueryPerformanceFrequency(&

d))

Freq=d.QuadPart;

return(TimeEnd.QuadPart-TimeStart.QuadPart)*1000/Freq;

}//返回时差

////////////////////////////////////////////////////////////

#defineN25/*通过修改N可改变运算位数,4N*/

#defineMAXN*4

voidinit(inta[],intb[],int*p1,int*p2)//数据初始化

inti,j;

charr,s;

for(i=0;

i<

MAX;

i++)

{a[i]=0;

b[i]=0;

printf("

输入a的值\n"

);

r=getchar();

if(r==45)

{

a[0]=r;

for(i=1;

(r=getchar())!

='

\n'

;

a[i]=r-48;

else

a[1]=r-48;

for(i=2;

*p1=i;

输入b的值\n"

s=getchar();

if(s==45)

b[0]=s;

for(j=1;

(s=getchar())!

j++)

b[j]=s-48;

b[1]=s-48;

for(j=2;

b[

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 职业教育 > 中职中专

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2