高精度计算
利用计算机进行数值计算,有时会遇到这样的问题:有些计算要求精度高,希望计算的数的位数可达几十位甚至几百位,虽然计算机的计算精度也算较高了,但因受到硬件的限制,往往达不到实际问题所要求的精度。我们可以利用程序设计的方法去实现这样的高精度计算。介绍常用的几种高精度计算的方法。
高精度计算中需要处理好以下几个问题:
数据的接收方法和存贮方法
数据的接收和存贮:当输入的数很长时,可采用字符串方式输入,这样可输入数字很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组中。
void init(int a[]) //传入一个数组 { string s; cin >> s; //读入字符串s a[0] = s.length(); //用a[0]计算字符串s的位数 for (i = 1; i <= a[0]; i++) a[i] = s[a[0] - i] - '0'; //将数串s转换为数组a,并倒序存储 }
另一种方法是直接用循环加数组方法输入数据。
void init(int a[]) { char num; int b[1000], _size = 0; while (scanf("%c", &num) && num <= '9' && num >= '0') { b[_size] = num - '0'; _size++; } a[0] = _size ; for (int i = 1; i <= _size; i++) { a[i] = b[_size-i]; } }
高精度数位数的确定
位数的确定:接收时往往是用字符串的,所以它的位数就等于字符串的长度。
进位,借位处理
加法进位
//核心思想 c[i] = a[i] + b[i]; if (c[i] >= 10) { c[i] %= 10; ++c[i + 1]; } //核心算法代码 int c[100]; void add(int a[], int b[]) //a,b,c都为数组,分别存储被加数、加数、结果 { int i = 1, x = 0; //x是进位 while ((i <= a数组长度) || (i <= b数组的长度)) { c[i] = a[i] + b[i] + x; //第i位相加并加上次的进位 x = c[i] / 10; //向高位进位 c[i] %= 10; //存储第i位的值 i++; //位置下标变量 } }
【例1】高精度加法。输入两个正整数,求它们的和。
【分析】 输入两个数到两个变量中,然后用赋值语句求它们的和,输出。但是,我们知道,在C++语言中任何数据类型都有一定的表示范围。而当两个被加数很大时,上述算法显然不能求出精确解,因此我们需要寻求另外一种方法。在读小学时,我们做加法都采用竖式方法,如图1。 这样,我们方便写出两个整数相加的算法。
A3A2A1
+ B3B2B1
————————————
C4C3C2C1
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int main() { char a1[100], b1[100]; int a[100], b[100], c[100], lena, lenb, lenc, i, x; memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); memset(c, 0, sizeof(c)); gets(a1); gets(b1); //输入加数与被加数 lena = strlen(a1); lenb = strlen(b1); for (i = 0; i <= lena - 1; i++) a[lena - i] = a1[i] - 48; //加数放入a数组 for (i = 0; i <= lenb - 1; i++) b[lenb - i] = b1[i] - 48; //加数放入b数组 lenc = 1; x = 0; while (lenc <= lena || lenc <= lenb) { c[lenc] = a[lenc] + b[lenc] + x; //两数相加 x = c[lenc] / 10; c[lenc] %= 10; lenc++; } c[lenc] = x; if (c[lenc] == 0) lenc--; //处理最高进位 for (i = lenc; i >= 1; i--) cout << c[i]; //输出结果 cout << endl; system("pause"); return 0; }
减法借位
if (a[i] < b[i]) { --a[i + 1]; a[i] += 10; } c[i] = a[i] - b[i];
【例2】高精度减法。输入两个正整数,求它们的差。
【算法分析】 类似加法,可以用竖式求减法。在做减法运算时,需要注意的是:被减数必须比减数大,同时需要处理借位。高精度减法的参考程序:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int main() { int a[256], b[256], c[256], lena, lenb, lenc, i; char n[256], n1[256], n2[256]; memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); memset(c, 0, sizeof(c)); printf("Input minuend:"); gets(n1); //输入被减数 printf("Input subtrahend:"); gets(n2); //输入减数 if (strlen(n1) < strlen(n2) || (strlen(n1) == strlen(n2) && strcmp(n1, n2) < 0)) //strcmp()为字符串比较函数,当n1==n2, 返回0; //n1>n2时,返回正整数;n1<n2时,返回负整数 { //处理被减数和减数,交换被减数和减数 strcpy(n, n1); //将n1数组的值完全赋值给n数组 strcpy(n1, n2); strcpy(n2, n); cout << "-"; //交换了减数和被减数,结果为负数 } lena = strlen(n1); lenb = strlen(n2); for (i = 0; i <= lena - 1; i++) a[lena - i] = int(n1[i] - '0'); //被减数放入a数组 for (i = 0; i <= lenb - 1; i++) b[lenb - i] = int(n2[i] - '0'); //减数放入b数组 i = 1; while (i <= lena || i <= lenb) { if (a[i] < b[i]) { a[i] += 10; //不够减,那么向高位借1当10 a[i + 1]--; } c[i] = a[i] - b[i]; //对应位相减 i++; } lenc = i; while ((c[lenc] == 0) && (lenc > 1)) lenc--; //最高位的0不输出 for (i = lenc; i >= 1; i--) cout << c[i]; //输出结果 cout << endl; system("pause"); return 0; }
乘法进位
c[i + j - 1] = a[i] * b[j] + x + c[i + j - 1]; x = c[i + j - 1] / 10; c[i + j - 1] %= 10;
商和余数的求法
商和余数处理:视被除数和除数的位数情况进行处理
转载请注明出处:https://www.cnblogs.com/stu-jyj3621

浙公网安备 33010602011771号