高精度运算和简单优化方法(C语言)_第1页
高精度运算和简单优化方法(C语言)_第2页
高精度运算和简单优化方法(C语言)_第3页
高精度运算和简单优化方法(C语言)_第4页
高精度运算和简单优化方法(C语言)_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、高精度运算和简单优化方法(C语言) 收藏先介绍一种高精度的优化方法,事实上这种优化没有改变算法的时间复杂度,也就是没有改变他的增长曲线但却使增长变慢了。然后再介绍一下减法。现在常用的高精度计算方法是把字符串中每个字符转化为一个数倒序存储在另一个数组中,这样做既浪费空间,又没有时效。因为最简单的整型数char最大可以存储255,用它存储个位数浪费了很多空间。而且逐位计算也花费很多时间。不如让一个数存储尽可能多的位,这样对一个数组元素的计算只需要一次,那么总的循环次数相应的缩短为几分之一,比如让char存储两位数(它不可以存储三位数因为最大的三位数999超出了它的范围)那么计算12+34的运算也相

2、应的成为一次普通的计算,而不需要向原始的方法那样循环两次。我在下面这个程序中用了long,因为long可以存储最多10位的数,因此可以用它存储任意9 位数,处理的时候注意如果它的位数不是九的倍数那么会有多余,把多余的放到最高位。这样做可以把循环次数缩小为1/9。这相当于是一个 1000000000进制的计算,用10进制显示它的每一位,发现这样一个1000000000进制的数它的显示与10进制完全一样的。但要注意的是,它的每一位输出必须为9位。如果10进制下小于九位则要在前面补零。比如某一位是100,在1000000000进制的数中要输出为000000100,c 语言有该格式的应用,pascal

3、中MS要计算前补零了,如果是最高位的话当然可以把前面的零省掉了。下面是该算法的程序#include<stdio.h>#include<string.h>int main()char a1100000,b1100000;long a10000=0,b10000=0,c10000=0,sa,sb,la,lb,lena,lenb,p,i,j,k,x=0,lenc,l;gets(a1); /读入gets(b1);la=strlen(a1); /算长度lb=strlen(b1);sa=la%9; /计算每九位划分后的剩余位数sb=lb%9;lena=la/9; lenb=lb/9

4、;k=1;for(p=sa-1;p>=0;p-)alena+=(a1p-48)*k;k*=10; /处理第一个加数,每九位划分后剩余的位数转化为一个数p=sa;for(i=lena-1;i>=0;i-) /每九个字符转换为一个九位数存储在ai中k=100000000;for(j=1;j<=9;j+)ai+=(a1p-48)*k;k/=10;p+=1;k=1;for(p=sb-1;p>=0;p-)blenb+=(b1p-48)*k;k*=10; /处理第二个加数,同上p=sb;for(i=lenb-1;i>=0;i-)k=100000000;for(j=1;j<

5、;=9;j+)bi+=(b1p-48)*k;k/=10;p+=1;i=0;while (i<=lena)|(i<=lenb) /计算ci=ai+bi+x;x=ci/1000000000;ci%=1000000000;i+;if (x!=0)lenc=i;clenc=x; /计算结果有没有增位else lenc=i-1;for(i=lenc;i>=0;i-)if (i!=lenc)printf("%09ld",ci);else printf("%ld",ci); /出开头按九位数输出return 0;以下是一个pascal的高精度的乘法,

6、原理同上,我只做了100进制,读者可以自己扩展。program acb;varla,lb,lc,x,i,j,l:integer;s,st:ansistring;a,b,c:array1.100000of byte;f1,f2:text;beginassign(f1,'qlwy.in');reset(f1);assign(f2,'qlwy.out');rewrite(f2);readln(f1,s);la:=length(s); l:=la; i:=1;while l+2>0 dobeginif l-1>0 thenst:=sl-1+sl else s

7、t:=sl;val(st,ai);i:=i+1; l:=l-2;end;if la mod 2=0 then la:=la div 2 else la:=la div 2+1;for i:=la downto 1 do writeln(f2,ai);readln(f1,s);lb:=length(s); l:=lb; i:=1;while l+2>0 dobeginif l-1>0 thenst:=sl-1+sl else st:=sl;val(st,bi);i:=i+1; l:=l-2;end;if lb mod 2=0 then lb:=lb div 2 else lb:=lb

8、 div 2+1;for i:=lb downto 1 do writeln(f2,bi);for i:=1 to la dobeginx:=0;for j:=1 to lb dobeginx:=ai*bj+x div 100+ci+j-1;ci+j-1:=x mod 100;end;ci+j:=x div 100;end;lc:=i+j;while (clc=0)and(lc>1)do dec(lc);for i:=lc downto 1 dobeginif ci<10 then write(f2,0);补零write(f2,ci);end;close(f1);close(f2)

9、;end.减法的关键在于符号和借位的问题,判断符号只要判断被减数与减数的大小即可,可以从位数与首位大小来判断。借位的问题其实不需要作任何判断,不论如何都向前借一位,然后再像加法进位一样进上去就行了。#include <stdio.h>char a11000,b11000,d,a1000,b1000,c1000;int la,lb,lc,i,x;void t1()d=0; /符号为正,将数据倒置存放,使个位在数组0下标for(i=0;i<la;i+)ai=a1la-i-1-'0'for(i=0;i<lb;i+)bi=b1lb-i-1-'0'

10、void t2()d='-' /符号为负,并交换倒置减数被减数for(i=0;i<la;i+)bi=a1la-i-1-'0'for(i=0;i<lb;i+)ai=b1lb-i-1-'0'int main()gets(a1); /读入gets(b1);la=strlen(a1); /算长度lb=strlen(b1);memset(b,0,sizeof(b); /数组的初始化memset(a,0,sizeof(a);memset(c,0,sizeof(c);if(la>lb)t1();if(la=lb)if(strcmp(a1,b1

11、)>=0)t1();else t2();if(la<lb)t2();i=0;x=0; /计算while(i<la|i<lb)x=ai+10-bi+x;ci=x%10;ai+1-=1;x=x/10;i+;while(ci=0&&i>0)i-; /计算结果的实际长度,去前零lc=i;if(d)printf("%c",d); /符号for(i=lc;i>=0;i-)printf("%d",ci);printf("n");return 0;除法的计算与前面的算法有所不同,由于除法不是一位一位

12、的进行运算,所以直接用单精度的除法操作不能得到一个高精度的除法运算,要用减法一次次的数出商的每一位。因此比较繁琐,为方便起见,在除法前要先写一个减法的函数以方便使用和简化结构。也可以用前面的优化措施,这道程序是每4位存储在一个变量中的,但这样或许会造成一些不好,因为如果是逐位的作减法得到商12 只要三次减法即可,如果压缩却要进行12次减法,但在大数据中却节省了移位这个复杂的过程的运算次数,因为在除法笔算的算法中,余数要拿下被除数的一位加在末尾做下一次除法,这个过程在程序中是很复杂的,存储余数的d数组末尾在0端,没有空余的位置把被除数加下来,所以要有一个向左移位的过程,这个过程执行的效率与这个数

13、组的有效位数密切相关,因为要从最高位开始全部向左移位,压缩后的数据有效位成了原来的1/4,而且做这种移位的次数也成了原来的1 /4,减法的执行效率也有一定提高,这样,对于大的数据来说是抛砖引玉之策 了。#include <stdio.h>#include<string.h>void convert(char*a, int*b) /转置int la, i, lm, k, j;la = strlen(a);lm = la % 4;b0 = la / 4; /0下标为有效位的长度if (lm > 0) b0+;bb0 = 0;k = 1;for (i = lm - 1;

14、 i >= 0; i-) bb0 += (ai - '0') * k;k *= 10;j = 1;k = 1;for (i = la - 1; i >= lm; i-) if (k = 10000) k = 1;j+;bj += (ai - '0') * k;k *= 10;void substration(int *a, int *b, int*c) /减法 int i, x;i = 1;x = 0;while (i <= a0 | i <= b0) ai + 1-;ci = 10000 + x + ai - bi;x = ci / 1

15、0000;ci %= 10000;i+;c0 = i - 1;while (cc0 = 0 && c0 > 1) /去掉最高位的0 c0-;int compare(int*a, int*b) /高精度比较int i = a0;int s = 0;if (a0 != b0)return (a0 - b0); /长度不同的,长的数为大 else while (s = 0 && i > 0) /不同按字典序比较s = ai - bi;i-;return s;void mult10000(int*a) /向左移位一次int i;for (i = a0; i

16、>= 1; i-)ai + 1 = ai;a1 = 0;a0 += 1;while (aa0 = 0 && a0 > 1) /去掉最高位的0a0 -= 1;void division(int *a, int *b, int *c, int *d) /a被除数,b除数,c商,d余数 int i;for (i = 0; i < 800; i+)ci = 0; /初始化数组cd0 = 1;d1 = 0; /初始化数组di = a0;while (i > 0) mult10000(d);d1 = ai;while (compare(d, b) >= 0)

17、substration(d, b, d);ci+;if (c0 = 0)c0 = i; /最高位i-;if (c0 = 0)c0 = 1; /商为0void output(int*a) /输出int i;printf("%d", aa0);for (i = a0 - 1; i >= 1; i-) printf("%04d", ai);int main() int a800, b800, c800, d800;char a1805, b1805;while (scanf("%s%s", a1, b1) != EOF) memset(a, 0, size

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论