C++高精度算法

目录

目录

前言: 

思路:

高精度加法:

高精度减法:

高精度乘法:

高精度除法:

 代码:

一、高精度加法

二、高精度减法 

三、高精度乘法 

四、高精度除法

最后


前言: 

        计算机最初、也是最重要的应用就是数值运算。在编程进行数值运算时,有时会遇到运算的精度要求特别高,远远超过各种数据类型的精度范围;有时数据又特别大,远远超过各种数据类型的极限值。这种情况下,就需要进行“高精度运算”。

        高精度运算首先要处理好数据的接受和存储问题,其次要处理好运算过程中的“进位”和“借位”问题。

引用自百度百科

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

思路:


高精度加法:

        用字符串输入两个数,再导入数组,然后每位相加,如果某位数字>10,则此位模10,下一位加一,最后用while循环去除前导零再输出即可。

高精度减法:

        用字符串输入两个数,再导入数组,判断是否后数比前数,如果是则输出负号再交换数组。然后按位相减不够借1,最后用while循环去除前导零再输出即可。

高精度乘法:

        导入方法与前面一样,导入后按乘法竖式思路相乘,再按常规思路进位。最后去除前导零就行了。

高精度除法:

        比较复杂不做过多解释。 

 代码:

一、高精度加法

#include<bits/stdc++.h>
using namespace std;
#define maxx 1145 //最长值(默认1145位)

char sa[maxx], sb[maxx];
int la, lb, lc, a[maxx], b[maxx], c[maxx];
int main() {
	scanf("%s %s", sa, sb);//读入字符串

	la = strlen(sa);
	lb = strlen(sb);
//	格式化字符串,看情况
//	memset(a, 0, sizeof(a));
//	memset(b, 0, sizeof(b));
//	memset(c, 0, sizeof(c));

//正序将字符串写入到数组A,B中
	for (int i = 0; i < la; i++) {
		a[la - i - 1] = sa[i] - '0';
	}
	for (int i = 0; i < lb; i++) {
		b[lb - i - 1] = sb[i] - '0';
	}

	lc = la > lb ? la : lb;//更新长度数据

	//模拟竖式加法
	for (int i = 0; i < lc; i++) {

		c[i] = a[i] + b[i] + c[i];
		if (c[i] > 10) { //进位
			c[i + 1] = 1;
			c[i] -= 10;
		}
	}
	if (c[lc] > 0)lc++;//更新长度

	//逆序打印输出
	for (int i = lc - 1; i >= 0; i--) {
		printf("%d", c[i]);
	}
	return 0;
}

二、高精度减法 

#include <bits/stdc++.h>
using namespace std;

#define maxx 1145 //最长值(默认1145位)
char sa[maxx], sb[maxx];
char tmp[maxx];//交换字符串
int la, lb, lc, a[maxx], b[maxx], c[maxx];

int main() {
	scanf("%s %s", sa, sb);//读入字符串

	la = strlen(sa);
	lb = strlen(sb);
	//判断最终的结果符号
	if ((la < lb) || (la == lb && strcmp(sa, sb) < 0)) {
		//被减数小于减数,结果为负数
		printf("-");
		//交换数据
		strcpy(tmp, sa);
		strcpy(sa, sb);
		strcpy(sb, tmp);
		//更新长度数据
		la = strlen(sa);
		lb = strlen(sb);
	}
//	格式化字符串,看情况
//	memset(a, 0, sizeof(a));
//	memset(b, 0, sizeof(b));
//	memset(c, 0, sizeof(c));

//倒序将字符串写入到数组A,B中
	for (int i = 0; i < la; i++) {
		a[i] = sa[la - i - 1] - '0';
	}
	for (int i = 0; i < lb; i++) {
		b[i] = sb[lb - i - 1] - '0';
	}

	//模拟竖式减法
	for (int i = 0; i < la; i++) {

		if (a[i] < b[i]) { //借位
			a[i + 1]--;
			a[i] += 10;
		}
		c[i] = a[i] - b[i];
	}

	//删除前导零
	for (int i = la - 1; i >= 0; i--) {
		//因为我们是从索引 0 开始,所以最高位是保存在 len-1
		if (0 == c[i] && la > 1) {
			//注意要有 la>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
			la--;
		} else {
			//第一个不是零的最高位,结束删除
			break;
		}
	}

	//逆序打印输出
	for (int i = la - 1; i >= 0; i--) {
		printf("%d", c[i]);
	}
	return 0;
}

三、高精度乘法 

#include<bits/stdc++.h>
using namespace std;
#define maxx 1145
char sa[maxx], sb[maxx];
int la, lb, lc, jw, f, w, a[maxx], b[maxx], c[maxx * maxx];
int main() {
	scanf("%s", sa);
	scanf("%s", sb);
	la = strlen(sa);
	lb = strlen(sb);
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(b));
	memset(c, 0, sizeof(c));
	for (int i = 0; i < la; i++) {
		a[la - i - 1] = sa[i] - '0';
	}
	for (int i = 0; i < lb; i++) {
		b[lb - i - 1] = sb[i] - '0';
	}
	jw = 0;//存储每一次乘法产生的进位
	for (int i = 0; i < la; i++) {
		for (int j = 0; j < lb; j++) {
			f = a[i] * b[j]; //处理逐
			jw = f / 10;    //位乘,记
			f %= 10;       //录乘积
			w = i + j;    //和进位
			c[w] = c[w] + f; //a[i]*b[j]的结果存储到c[i+j]
			c[w + 1] = c[w + 1] + jw + c[w] / 10;//处理进位
			c[w] %= 10;
		}
	}
	lc = la + lb;//找到最高的非0位
	while (c[lc] == 0)lc--;
	if (lc < 0) {
		printf("0\n");
	} else for (int i = lc; i >= 0; i--) {
			printf("%d", c[i]);
		}
	return 0;
}

四、高精度除法

#include<bits/stdc++.h>
using namespace std;
#define maxx 10005
char sa[maxx], sb[maxx];
int la, lb, lc, a[maxx], b[maxx], c[maxx];
int main() {
    scanf("%s", sa);
    scanf("%s", sb);
    la = strlen(sa);
    lb = strlen(sb);
    if (lb > la || (lb == la && strcmp(sa, sb) < 0)) {//特判被除数小于除数的情况
        printf("0\n");
    } else {
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        memset(c, 0, sizeof(c));
        for (int i = 0; i < la; i++) {
            a[la - i - 1] = sa[i] - '0';
        }
        for (int i = 0; i < lb; i++) {
            b[lb - i - 1] = sb[i] - '0';
        }
        lc = la - lb;//计算c的长度
        for (int i = lc; i >= 0; i--) {//从高位到低位枚举c的每一位
            int k = 0;//记录当前位能够减去几个b
            while (k <= 9 && (k * b[0]) <= a[i + lb]) {//二分找到当前位能够减去几个b
                int mid = (k + 1 + 9) >> 1;
                if (mid*b[0] <= a[i + lb] - mid*b[1]) k = mid;
                else break;
            }
            c[i] = k;
            for (int j = 0; j < lb; j++) {
                a[i + j] -= c[i] * b[j];//更新a的值
                if (a[i + j] < 0) {//借位
                    a[i + j] += 10;
                    a[i + j + 1]--;
                }
            }
        }
        while (lc >= 0 && c[lc] == 0)lc--;
        if (lc < 0) {
            printf("0\n");
        } else for (int i = lc; i >= 0; i--) {
            printf("%d", c[i]);
        }
    }
    return 0;
}

最后

祝大家国庆快乐!!!

参考自

https://blog.csdn.net/hejx0412/article/details/123667293

https://baike.baidu.com/item/%E9%AB%98%E7%B2%BE%E5%BA%A6%E7%AE%97%E6%B3%95/1024900?fr=aladdin

https://blog.csdn.net/justidle/article/details/104426323?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166484827916782395372981%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=166484827916782395372981&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~hot_rank-3-104426323-null-null.142^v51^control,201^v3^control_1&utm_term=%E9%AB%98%E7%B2%BE%E5%BA%A6%E5%87%8F%E6%B3%95&spm=1018.2226.3001.4187

  • 7
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江河湖海 

最近手头有点紧,感谢你给我鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值