高精度计算(大数计算)

目录

一、高精度加法。(不考虑负数)

 二、高精度数减法

三、高精度乘法(两者都为整数,都为正数)

四、高精度除法。(两者都为正数且除数不为0)


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

一、高精度加法。(不考虑负数)

因为任何数据类型都有一定的表示范围。而当两个被加数很大时,在c语言中也没有任何一个数据类型可以储存该数据。如果我们用数组A、B分别存储加数和被加数,用数组C存储结果,就可以用下图来描述。

有几个需要注意的点。

1.使用字符串来储存数字,所以它是倒序储存的,我们计算时要从后面往前计算。

2.像这种倒序存放的数据的计算结果的输出要小心前导零的输出,所以我们也要消掉0再输出。

3.计算时要注意进位,每一次的计算下一位要先加上上一次计算的进位。

#include<stdio.h>
#include<string.h>
#define MAX 100010
int a[MAX] = { 0 };
int  b[MAX] = { 0 };
int c[MAX] = { 0 };
char ch[MAX];
int fun(char str[], int a[]) {//转换为数字
    char* p = ch;
    for (int i = strlen(ch) - 1; i >= 0; i--) {
        a[i] = (*p) - '0';
        p++;
    }
    return strlen(ch);//计算字符长度
}
int main() {
    int t = 0;
    int num1, num2;
    scanf("%s", &ch);
    num1 = fun(ch, a);//将字符数字转换为可计算的数字,顺便记录它的字符长度
    scanf("%s", &ch);
    num2 = fun(ch, b);
    if (num1 < num2) {//将两者的字符长度进行比较,用字符长的确保历遍两者的储存的数据
        int temp = num1;
        num1 = num2;
        num2 = temp;
    }
    int num;//初次计算当前位数两者结果
    for (int i = 0, k = num1; i <= num1; k--, i++) {//使用k来记录 计算结果 C 数组 长度还可以逆置计算结果,方便输出
        num = a[i] + b[i];//i为较长串,历遍两个数组

        if (t != 0) {//如果进位不为0说明,需要加上进位,再复零
            num += t; t = 0;
        }
        if (num < 10)//不需要进位
            c[k] = num;
        else
        {
            while (num >= 10) {//大于十则需要进位
                t++;
                num -= 10;
            }
            c[k] = num;//加上当前小于10时的最终数字
        }
    }
    if (c[0] == 0)//防止前导零的出现,可以通过t来控制,要是没有进入该条件,t则为0
        t = 1;
    for (int i = t; i <= num1; i++)
        printf("%d", c[i]);
    return 0;
}

 二、高精度数减法

1、和高精度加法相比,减法在差为负数时处理的细节更多一点:当被减数小于减数时,差为负数,差的绝对值是减数减去被减数;所以就要保持绝对值较大数作被减数,最后在结果前加上负号。计算就使用小学竖式计算即可。

2.运算:先判断当前位数的相减是否为负数,是否需要进行借位,借位后要在被借数减1。

3.也是需要判断前导零的情况之后,再将其输出。

#include<stdio.h>
#include<string.h>
#define MAX 100010
int fun(char str[], int str2[])//进行数据转换
{
        char* p = str;
        int num = strlen(str) - 1;
        for (int i = num, j = 0; j <= num; i--, j++)
            str2[i] = p[j] - '0';
        return num;
}
char str1[MAX], str2[MAX];//使用两个个字符数组储存,用于应对出现负数情况
int a[MAX], b[MAX], c[MAX];
int main() {
        scanf("%s", str1);
        scanf("%s", str2);
        int num1 = strlen(str1);//转换并返回字符长度
        int num2 = strlen(str2);
        if (num1 < num2 || num1 == num2 && strcmp(str1, str2) < 0) {//判断该计算是否会出现负数。

            //strcmp函数可以判断两个字符数组的长度,两个字符数组是否相等,这样就可以精准判断谁大。

                printf("-");
                num1 = fun(str2, a);//交换位置
                num2 = fun(str1, b);
        }
        else {
                num1 = fun(str1, a);//被除数大于除数的情况
                num2 = fun(str2, b);
        }
        //为了固定一个数组进行减法,所以要将两者进行比较长度,大小


        for (int i = 0; i <= num1; i++) {//计算次数为较大的数所拥有的位数


                if (a[i] < b[i]) {//出现借位情况

                        c[i] = a[i] - b[i] + 10;//避免计算结果过程出现负数,借一位就可以解决负数问题
                        a[i + 1]--;//相应的被借数减10
                }
                else {
                        c[i] = a[i] - b[i];
                }
        }
        while (c[num1] == 0 && num1 > 0)//消去前导零,当结果数组最前一位为零才消去
            num1--;//调整num1,

        for (int i = num1; i >= 0; i--)//倒序输出
            printf("%d", c[i]);
        return 0;
}

三、高精度乘法(两者都为整数,都为正数)

这里指的高精度乘法为,一个大整数乘一个小整数。

1.储存数字方式与前两个相同,计算稍有不同。

例如:(A2A1A0)*(B1B0)=>C0=A0*(B1B0),C1=A1*(B1B0),C2=A2*(B1B0);

使用较大整数的每一位与小整数相乘。计算的每一位结果与大整数对应的位置相同

2.需要进行进位时要注意对10取余可以快速获得进位。

3.进行循环计算跳出时,使用是否有剩余进位辅助判断是否计算完成。

#include <stdio.h>
#include<string.h>
#define MAX 100010
int fun(char str[], int str2[])
{
    char* p = str;
    int num = strlen(str) - 1;
    for (int i = num, j = 0; j <= num; i--, j++)
        str2[i] = p[j] - '0';
    return num + 1;
}
char str1[MAX];
int a[MAX] = { 0 };
int c[MAX] = { 0 };
int b;
int main()
{
    scanf("%s", &str1);
    scanf("%d", &b);
    int num1 = fun(str1, a);
    int j = 0;
    int t = 0;


    int i;//通过i进行了多少次操作可以获得计算结果的最高位数

        //t用于保存进位,和确认是否可以跳出循环
    for (i = 0; i < num1 || t != 0; i++) {//判断进行计算完成的条件为   t不等于零且计算结果的位数应大于或等与最大整数

        if (i < num1)//小于大整数是为了最后一位进行计算时仍有进位的情况,需要将t复零才可以确定完成计算

            t += a[i] * b;//加上之前进行进位

        c[i] = t % 10;//将t对10取余才能确保计算结果为小于10的整数,
        
        t /= 10;//保留大于10,用于下一位的进位

    }
    while (c[i] == 0 && i > 0)//除去前导零
        i--;

    for (; i >= 0; i--)//后导输出
        printf("%d", c[i]);
    return 0;
}

四、高精度除法。(两者都为正数且除数不为0)

与之前的高精度加法、减法、乘法不同,之前的都是从大整数的最小位进行计算,除法需要从高位进行计算。像小学的竖式计算一样,将大整数的每一位除以除数。需要保留上一位计算的余数继续计算。

#include <stdio.h>
#include <string.h>
#define MAX 100010
char str[MAX];
int a[MAX];
int b;
int c[MAX];
int main()
{
    scanf("%s", &str);
    scanf("%d", &b);
    int num = strlen(str) - 1;
    for (int i = 0, j = num; i <= num; i++, j--)//需要提前倒置除法
        a[j] = str[i] - '0';


    int t = 0;//记录余数


    for (int i = num; i >= 0; i--)
    {
        t = t * 10 + a[i];//保留上一位的余数进行计算

        c[i] = t / b;//将大整数的每一位除以小整数

        t %= b;//对b取余可以获得当前计算所留下的余数
    }
    while (c[num] == 0 && num > 1)//消去前导零
        num--;
    for (int i = num; i >= 0; i--)//逆置输出
        printf("%d", c[i]);
    printf("\n%d", t);
    return 0;

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值