高精度计算

利用计算机进行数值计算,有时会遇到这样的问题:有些计算要求精度高,希望计算的数的位数可达几十位甚至几百位,虽然计算机的计算精度也算较高了,但因受到硬件的限制,往往达不到实际问题所要求的精度。我们可以利用程序设计的方法去实现这样的高精度计算。介绍常用的几种高精度计算的方法。

高精度计算中需要处理好以下几个问题:

数据的接收方法和存贮方法

数据的接收和存贮:当输入的数很长时,可采用字符串方式输入,这样可输入数字很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组中。

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;

商和余数的求法

商和余数处理:视被除数和除数的位数情况进行处理

你可能感兴趣的:(算法,c++,数据结构,蓝桥杯,开发语言)