高精度计算(大数问题)

高精度计算(大数问题)

高精度介绍(百度来的O(∩_∩)O)

高精度算法,属于处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中,
用一个数组去表示一个数字,这样这个数字就被称为是高精度数。高精度算法就是能处理高精度数各种运算的算法,但又因其特殊性,故从普通数的算法中分离,自成一家。

高精度读入数据

高精度问题所设计到的数据都是很大的,c/c++的整数类型是储存不下的。因此当要输入一组大数时可以用字符串的方式输入到字符数组中,然后经过一系列操作再将字符数组的元素按位转化到整型数组中,在此我们需格外注意存到整型数组时要倒着存(将最低位存到数组开头)方便进行进位操作。并且我们常用整型数组第一位储存位数。
高精度计算(大数问题)_第1张图片

代码演示

#include 
#include 
char ch[100]= {0};
int num[100] = {0};

int main() {
    scanf("%s", ch);
    int len = strlen(ch);
    if (ans[0] < len) ans[0] = len;
    for(int i = 0; i < len; i++) {
        num[len - i] = ch[i] - '0';
    }
}

高精度加法

题目描述

计算出以下一百个50位数的和的前十位数字。

题目数据太长了就放在这了_

https://projecteuler.net/problem=13

解析

大数加法问题就是我们小学时候学的竖式加法,按位计算逢十进一。恩,就是这样。

代码演示

#include 
#include 

char num[55];
int ans[55] = {1, 0};

int main() {
    for (int i = 0; i < 100; i++) {
        scanf("%s", num);
        int len = strlen(num);
        if (ans[0] < len) ans[0] = len;
        for (int j = 0; j < len; j++) {
            ans[len - j] += (num[j] - '0');
        }
        for (int j = 1; j <= ans[0]; j++) {
            if (ans[j] < 10) continue;
            ans[j + 1] += ans[j] / 10;
            ans[j] %= 10;
            ans[0] += (j == ans[0]);
        }
    }
    //此处可以添加删除前导零的代码
    for (int i = ans[0]; i > ans[0] - 10; i--) {
        printf("%d", ans[i]);
    }
    printf("\n");
    return 0;
}

另外还有前导零的问题本题不涉及

while(ans[ans[0]] == 0 && ans[0] > 0) {
    ans[0]--;
}

高精度减法

题目描述

洛谷p2142高精度减法

https://www.luogu.org/problem/P2142

解析

减法和加法一样只是把进位变为借位,并且要注意输入数的大小,需要大减小

代码演示

#include
#include
#define max_n 20000

int num1[max_n] = {0};
int num2[max_n] = {0};
int ans[max_n] = {0};
char ch1[max_n] = {0};
char ch2[max_n] = {0};
char n[max_n] = {0};
int main() {
    scanf("%s", ch1);
    scanf("%s", ch2);
    int len1 = strlen(ch1);
    int len2 = strlen(ch2);
    //此处判断大小,若输入第一个数小于第二个数则把两个数交换,保证第一个数大
    if(len1 < len2 || (len1 == len2 && strcmp(ch2,ch1) > 0)) {
        strcpy(n, ch1);
        strcpy(ch1, ch2);
        strcpy(ch2, n);
        printf("-");//注意要加个负号
    }
    len1 = strlen(ch1);
    len2 = strlen(ch2);
    for(int i = 0; i < len1; i++) {
        num1[len1 - i] = ch1[i] - '0';
    }
    for(int i = 0; i < len2; i++) {
        num2[len2 - i] = ch2[i] - '0';
    }
    ans[0] = len1;//经过判断第一肯定最大,我们往往用数组第一位记录所存数字位数
    for(int i = 1; i <= ans[0]; i++) {
        if(num1[i] < num2[i]) {
            ans[i] = num1[i] + 10 - num2[i];
            num1[i + 1]--;
        }else {
            ans[i] = num1[i] - num2[i];
        }
    }
    while(ans[ans[0]] == 0 && ans[0] > 1) {
        ans[0]--;
    }
    for(int i = ans[0]; i >= 1; i--) {
        printf("%d", ans[i]);
    }
}

高精度乘法

题目描述

洛谷p1303 A * B Problem

https://www.luogu.org/problem/P1303

解析

乘法也和加法一样用乘法竖式

              1   2   3

×          5   6   7

——————————

​              7   14  216    12  18

 5   10   15   

——————————

5    16    34  32  21

可以这几组数据放在数组里然后在进行进位。假设将乘数放在a[i]里,将被乘数放在b[j]里,那么结果c[i + j - 1] += a[i] + b[j]

代码演示

#include
#include
char ch1[5000] = {0};
char ch2[5000] = {0};
int num1[5000] = {0};
int num2[5000] = {0};
int ans[5000] = {0};
int main() {
    scanf("%s", ch1);
    scanf("%s", ch2);
    int len1 = strlen(ch1);
    int len2 = strlen(ch2);
    for(int i = 0; i < len1; i++) {
        num1[len1 - i] = ch1[i] - '0';
    }
    for(int j = 0; j < len2; j++) {
        num2[len2 - j] = ch2[j] - '0';
    }
    for(int i = 1; i <= len1; i++) {
        for(int j = 1; j <= len2; j++) {
            ans[j + i - 1] +=  num1[i] * num2[j];
        }
    }
    ans[0] = len1 + len2;
    for(int i = 1; i <= ans[0]; i++) {
        if(ans[i] < 10) continue;
        ans[i + 1] += ans[i] / 10;
        ans[i] %=  10;
        ans[0] += (i == ans[0]);
    }
    while (ans[ans[0]] == 0 && ans[0] > 1){//前导零的问题
		ans[0]--;
	}
    for(int i = ans[0]; i >= 1; i--) {
        printf("%d", ans[i]);
    }
}

除法等以后更新

你可能感兴趣的:(C/C++)