利用计算机进行数值计算,有时会遇到这样的问题:有些计算要求精度高,希望计算的数的位数可达几十位甚至几百位,虽然计算机的计算精度也算较高了,但因受到硬件的限制,往往达不到实际问题所要求的精度。我们可以利用程序设计的方法去实现这样的高精度计算。介绍常用的几种高精度计算的方法。
高精度计算中需要处理好以下几个问题:
数据的接收方法和存贮方法
数据的接收和存贮:当输入的数很长时,可采用字符串方式输入,这样可输入数字很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组中。
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
#include
#include
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
#include
#include
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 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;
商和余数的求法
商和余数处理:视被除数和除数的位数情况进行处理