第二章高精度整数的算法
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for (int i = 0; i < MAXLEN; i++) c.s[i]=0; for (int i = 0; i < len; i++)
{ c.s[i]+=a.s[i]*b; c.s[i+1]+=c.s[i]/10; c.s[i] = c.s[i]%10;
} while ((c.s[len-1] >= 10)) { c.s[len]+=c.s[len-1]/10;
//调整当前位
}
if (c.s[len]>0) len++;
//调整结果长
}
说明
C各位清0: for (int i = 0; i <= len; i++) c.s[i]=0;
也可以用 memset()函数 memset(c.s,0,len);
三、减法运算 c=a-b (a,b,c为Integer类型,a>b)
a.s[i] = (int)(s[a.len-1-i])-’0’;
48
二、加法运算 c=a+b (a,b,c为Integer类型)
1.首先,确定a和b中的最大位数 x (x = max { a.len , b.len } ).
2.然后依照由低位至高位(第0位至第x-1位)的顺 序进行加法运算。在每一次位运算中,a.s当前 位加b.s当前位的和除以 10 ,其整商即为进位, 其余数即为和的当前位。
例如整数 x 含有 k 个因子i,
我们按照上述方法依次处理 x 的每一个因子, 得出的 num 即为积或商。
本章复习题
一、高精度加法运算算法 二、乘法(高精度*高精度) (注意:不能忘记数据结构)
{
public:
int len;
// 长度
int s[MAXLEN]; // 表示整数的数组
};
Integer a,b;
将数字串转化为整数数组 a 的 方法如下:
Char[MAXLEN] s; cin>>s; a.len = strlen(s); for (int i = 0; i < a.len; i++)
1 从数据结构上作进一步改进,充分利用内 存空间,提高算法的空间效率。上述算法有 很大的改进空间。
2 改进算法的时间复杂性,特别是乘法和除 法的算法效率,用大整数的乘法算法或更好 的算法作深入改进。
3 将上述算法扩展到高精度实数算法。 4 将上述算法扩展到高精度分数算法。
改善高精度运算的效率
3.在进行了x-1位的加法后,若最高位有进位 ( c.s [x]不等于0 ) ,则 c.s 的长度为x+1 。
Integer plus(Integer a, Integer b)
{ Integer c;
//保存返回值
int len=a.len>b.len?a.len:b.len; //确定最大位数
C语言描述
#define MAXLEN 10000
typedef struct
{
int len;
/* 长度 */
int s[MAXLEN]; /* 表示整数的数组 */
} Integer;
Integer a,b;
C++语言描述
const int MAXLEN=10000;
class Integer
1.扩大进制数:
我们可以考虑用一个数记录2位数字、3位数字或更多 位数字。
理论上来说,数组中的每个数表示的数字越多,数组 的长度就越短,程序运行的时间也就越短。但是,我 们还需考虑到计算机中的一个数的取值范围,必须保 证它们在运算过程中不会越界。
在权衡了两方面的情况后得出:用一个 long int 记录 4 位数字是最佳的方案。那么这个数组就相当于一个 10000 进制的数,其中每一个元素都是 10000 进制 下的一位数。
if (c.s[i]<0) { c.s[i]+=10;c.s[i+1]--; } } while ((len>1) && (c.s[len] == 0))len--; c.len = len; return c; }
四、乘法(高精度*单精度) c=a*b (a,c为Integer,b为int)
按照乘法规则,从 a 的第 0 位开始逐位与b相 乘。
以上接触到的高精度存储方法是用一个整型 数组来表示一个很大的数,数组中的每一个 数表示一位十进制数字。但这种方法的缺点 是,如果十进制数的位数很多,则对应数组 的长度会很长,并增加了高精度计算的时间。 那么有什么方法可以改善高精度运算的效率 呢?下面,我们给出两种方法:
1.扩大进制数: 2.建立因子表:
while ((len > 1) && (c.s[len-1] == 0)) len--; c.len = len; return c; }
六.对上述算法的评价
优点: 思路清晰,描述简单,易于实现。
缺点: 1 用整型向量存储高精度数,浪费空间。 2 用到的算法虽然简单,但效率太差。
对上述算法的改进意见
for (int i = 0; i <= len; i++) c.s[i]=0; //C各位清0
for (i = 0; i < len; i++)
{ c.s[i]+=a.s[i]+b.s[i];
//对应位相加
if (c.s[i]>=10)
{ c.s[i]-=10;
//调整进位
c.s[i+1]++;}
for (int i =0; i < len; i++) c.s[i]=0; for (int i = 0; i < a.len; i++)
for (int j = 0; j < b.len; j++) { c.s[i+j-1]+=a.s[i]*b.s[j]; c.s[i+j]+=c.s[i+j-1]/10; c.s[i+j-1] = c.s[i+j-1] % 10; }
Integer minus(const Integer& a, const Integer& b) { // a>b>0
Integer c; int len =a.len; for (int i = 0; i < len; i++) c.s[i]=0; for (i = 0; i < len; i++) { c.s[i]+=a.s[i]-b.s[i];
c.s[len-1]=c.s[len-1] % 10; len++; } while ((len >1) && (c.s[len-1] == 0)) len--; c.len = len; return c;
五、乘法(高精度*高精度)
Integer mul2(const Integer& a, const Integer& b) { Integer c; int len = a.len + b.len + 1;
1.依照由低位至高位(第0位至第len-1位)的顺 序进行减法运算。
2.在每一次按位运算中,若出现不够减的情况 (a.s[i]<b.s[i]) ,则向高位借位 { a.s[i+1]- - , a.s[i] = a[i]+10 }。
3.在进行了len位的减法后,若最高位为零 ( c.s[len-1] = 0 ) ,则 c的长度减 1 。
在第 i 位乘法运算中(0<=i<=a.len-1 ) , a 的 i 位与b的乘积必须加上i-1位的进位(i-1位 的乘积除以10的整商),然后规整积的i位(取 i位的乘积对10的余数)。
Integer mul1(const Integer& a,int b) { Integer c; int len = a.len;
Pascal语言的常用数据类型
C++常用基本类型
问题的提出
程序设计语言所处理加工的各类数据都有 相应的值域限定,一旦某类型的数据超出了规 定的范围,运算结果就会出错。
但是在有些试题中,变量运算对象的数值 范围是任何数据类型所载法容纳的,因此人们 不得不采用高精度运算。
数据结构
由于待处理的数据超过了任何一种数据类 型所能容纳的范围,因此必须采用数字串的形 式输入,并将其转化为整数数组。该数组的每 一个元素对应一位十进制数,由其下标顺序指 明位序号。运算规则如同算术运算。由于高精 度运算的结果可能使得数据长度发生增减,因 此除需要用整数数组存储数据外,还需要用一 个整数变量记录整数数组的元素个数,即数据 的实际长度。
两个整数( 10000 进制)数组的加法和减法与前面 所讲的十进制运算方法相比,除了进制数有所变化外, 其他没有什么区别。
2.建立因子表:
任何自然数都可以表示为一系列质因数的乘积方式。
pl , p2 , … , pt为质因子。设 num 数组为自然数 n ,其中 num[i]为因子i的次幂数。显然, num[k], num[k-1] , … , num[1]构成了一个自然数,有了 自然数 n 的因子表 num ,就可以十分方便地进行乘 法或除法运算。
{ c.s[i]+=a.s[i]*b; c.s[i+1]+=c.s[i]/10; c.s[i] = c.s[i]%10;
} while ((c.s[len-1] >= 10)) { c.s[len]+=c.s[len-1]/10;
//调整当前位
}
if (c.s[len]>0) len++;
//调整结果长
}
说明
C各位清0: for (int i = 0; i <= len; i++) c.s[i]=0;
也可以用 memset()函数 memset(c.s,0,len);
三、减法运算 c=a-b (a,b,c为Integer类型,a>b)
a.s[i] = (int)(s[a.len-1-i])-’0’;
48
二、加法运算 c=a+b (a,b,c为Integer类型)
1.首先,确定a和b中的最大位数 x (x = max { a.len , b.len } ).
2.然后依照由低位至高位(第0位至第x-1位)的顺 序进行加法运算。在每一次位运算中,a.s当前 位加b.s当前位的和除以 10 ,其整商即为进位, 其余数即为和的当前位。
例如整数 x 含有 k 个因子i,
我们按照上述方法依次处理 x 的每一个因子, 得出的 num 即为积或商。
本章复习题
一、高精度加法运算算法 二、乘法(高精度*高精度) (注意:不能忘记数据结构)
{
public:
int len;
// 长度
int s[MAXLEN]; // 表示整数的数组
};
Integer a,b;
将数字串转化为整数数组 a 的 方法如下:
Char[MAXLEN] s; cin>>s; a.len = strlen(s); for (int i = 0; i < a.len; i++)
1 从数据结构上作进一步改进,充分利用内 存空间,提高算法的空间效率。上述算法有 很大的改进空间。
2 改进算法的时间复杂性,特别是乘法和除 法的算法效率,用大整数的乘法算法或更好 的算法作深入改进。
3 将上述算法扩展到高精度实数算法。 4 将上述算法扩展到高精度分数算法。
改善高精度运算的效率
3.在进行了x-1位的加法后,若最高位有进位 ( c.s [x]不等于0 ) ,则 c.s 的长度为x+1 。
Integer plus(Integer a, Integer b)
{ Integer c;
//保存返回值
int len=a.len>b.len?a.len:b.len; //确定最大位数
C语言描述
#define MAXLEN 10000
typedef struct
{
int len;
/* 长度 */
int s[MAXLEN]; /* 表示整数的数组 */
} Integer;
Integer a,b;
C++语言描述
const int MAXLEN=10000;
class Integer
1.扩大进制数:
我们可以考虑用一个数记录2位数字、3位数字或更多 位数字。
理论上来说,数组中的每个数表示的数字越多,数组 的长度就越短,程序运行的时间也就越短。但是,我 们还需考虑到计算机中的一个数的取值范围,必须保 证它们在运算过程中不会越界。
在权衡了两方面的情况后得出:用一个 long int 记录 4 位数字是最佳的方案。那么这个数组就相当于一个 10000 进制的数,其中每一个元素都是 10000 进制 下的一位数。
if (c.s[i]<0) { c.s[i]+=10;c.s[i+1]--; } } while ((len>1) && (c.s[len] == 0))len--; c.len = len; return c; }
四、乘法(高精度*单精度) c=a*b (a,c为Integer,b为int)
按照乘法规则,从 a 的第 0 位开始逐位与b相 乘。
以上接触到的高精度存储方法是用一个整型 数组来表示一个很大的数,数组中的每一个 数表示一位十进制数字。但这种方法的缺点 是,如果十进制数的位数很多,则对应数组 的长度会很长,并增加了高精度计算的时间。 那么有什么方法可以改善高精度运算的效率 呢?下面,我们给出两种方法:
1.扩大进制数: 2.建立因子表:
while ((len > 1) && (c.s[len-1] == 0)) len--; c.len = len; return c; }
六.对上述算法的评价
优点: 思路清晰,描述简单,易于实现。
缺点: 1 用整型向量存储高精度数,浪费空间。 2 用到的算法虽然简单,但效率太差。
对上述算法的改进意见
for (int i = 0; i <= len; i++) c.s[i]=0; //C各位清0
for (i = 0; i < len; i++)
{ c.s[i]+=a.s[i]+b.s[i];
//对应位相加
if (c.s[i]>=10)
{ c.s[i]-=10;
//调整进位
c.s[i+1]++;}
for (int i =0; i < len; i++) c.s[i]=0; for (int i = 0; i < a.len; i++)
for (int j = 0; j < b.len; j++) { c.s[i+j-1]+=a.s[i]*b.s[j]; c.s[i+j]+=c.s[i+j-1]/10; c.s[i+j-1] = c.s[i+j-1] % 10; }
Integer minus(const Integer& a, const Integer& b) { // a>b>0
Integer c; int len =a.len; for (int i = 0; i < len; i++) c.s[i]=0; for (i = 0; i < len; i++) { c.s[i]+=a.s[i]-b.s[i];
c.s[len-1]=c.s[len-1] % 10; len++; } while ((len >1) && (c.s[len-1] == 0)) len--; c.len = len; return c;
五、乘法(高精度*高精度)
Integer mul2(const Integer& a, const Integer& b) { Integer c; int len = a.len + b.len + 1;
1.依照由低位至高位(第0位至第len-1位)的顺 序进行减法运算。
2.在每一次按位运算中,若出现不够减的情况 (a.s[i]<b.s[i]) ,则向高位借位 { a.s[i+1]- - , a.s[i] = a[i]+10 }。
3.在进行了len位的减法后,若最高位为零 ( c.s[len-1] = 0 ) ,则 c的长度减 1 。
在第 i 位乘法运算中(0<=i<=a.len-1 ) , a 的 i 位与b的乘积必须加上i-1位的进位(i-1位 的乘积除以10的整商),然后规整积的i位(取 i位的乘积对10的余数)。
Integer mul1(const Integer& a,int b) { Integer c; int len = a.len;
Pascal语言的常用数据类型
C++常用基本类型
问题的提出
程序设计语言所处理加工的各类数据都有 相应的值域限定,一旦某类型的数据超出了规 定的范围,运算结果就会出错。
但是在有些试题中,变量运算对象的数值 范围是任何数据类型所载法容纳的,因此人们 不得不采用高精度运算。
数据结构
由于待处理的数据超过了任何一种数据类 型所能容纳的范围,因此必须采用数字串的形 式输入,并将其转化为整数数组。该数组的每 一个元素对应一位十进制数,由其下标顺序指 明位序号。运算规则如同算术运算。由于高精 度运算的结果可能使得数据长度发生增减,因 此除需要用整数数组存储数据外,还需要用一 个整数变量记录整数数组的元素个数,即数据 的实际长度。
两个整数( 10000 进制)数组的加法和减法与前面 所讲的十进制运算方法相比,除了进制数有所变化外, 其他没有什么区别。
2.建立因子表:
任何自然数都可以表示为一系列质因数的乘积方式。
pl , p2 , … , pt为质因子。设 num 数组为自然数 n ,其中 num[i]为因子i的次幂数。显然, num[k], num[k-1] , … , num[1]构成了一个自然数,有了 自然数 n 的因子表 num ,就可以十分方便地进行乘 法或除法运算。