概念

在我们进行计算的过程中,经常会遇到几十位,甚至几百位的数字的计算问题,也有可能会遇到小数点后几十位,几百位的情况,而我们面对这样的情况下,   和 的数据范围显然是不够使用的了。因此这时,我们就需要引入一个新的算法,叫做高精度算法 .

我们可以利用程序设计的方法去实现这样的高精度计算 . 介绍常用的几种高精度计算的方法 .

思想

高精度算法本质上是用字符串模拟数字进行计算,再利用类似于数学里的竖式的形式,一位一位进行相关计算 .

处理

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

1)数据的接收方法和存储方法

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

void init(int a[]) { // 传入数组string s;cin >> s; len = s.length(); // s.length --> 计算字符串位数for(int i=1; i<=len; i++)     a[i] = s[len -i] - '0'; //将字符串s转换为数组a, 倒序存储
}

2)进位、借位的处理.

// 加法进位: c[i] = a[i] + b[i]code:    if(c[i] >= 10) {c[i] %= 10;++c[i++];}//减法借位: c[i] = a[i] - b[i]code:    if(a[i] < b[i]) {--a[i+1];a[i] += 10;   } //乘法进位: c[i + j - 1] = a[i] * b[j] + x + c[i + j - 1];x = c[i + j - 1] / 10;c[i + j - 1] % 10;

高精度加法 +

输入两个数到变量中,然后用赋值语句求它们的和后输出 . But,我们知道,在 C++ 语言中任何数据类型都有一定表示范围. 当两个加数很大时,以前的算法显然不能求出精确解,因此我们需要寻求另一种方法 .在读小学时,我们做加法都采用竖式方法 . 这样我们方便写出两个整数相加的算法 .

如果我们用数组分别储存两个加数,用数组 储存结果。则上例有 :

#include <cstdio>
#include <cstring>using namespace std;int main() {char a1[5005], b1[5005]; //用字符存储数字int a[5005], b[5005], c[5005]; //c[i] 用来储存每位相加的结果int len_a, len_b, len_c = 1, x, i;memset(a, 0, sizeof(a));memset(b, 0, sizeof(b));memset(c, 0, sizeof(c));scanf("%s%s", a1, b1); //输入两个加数len_a = strlen(a1);len_b = strlen(b1);for(i=0; i<len_a; i++) a[len_a - i] = a1[i] - '0'; // 将加数放进a数组for(i=0; i<len_b; i++) b[len_b - i] = b1[i] - '0'; // 将另一个加数放进b数组x = 0; // x为进位while(len_c <= len_a || len_c <= len_b) {c[len_c] = a[len_c] + b[len_c] + x; // 两数相加,再加上前两个数进位的x = c[len_c] / 10; // 刷新进位c[len_c] %= 10; // 进位后剩下的len_c++; //位数加1}c[len_c] = x;if(c[len_c] == 0) { //判断首位是否为0len_c--; // 不输出此位}for(int i=len_c; i>=1; i--) {printf("%d", c[i]); //输出每一位的数}return 0;
}

高精度减法 -

类似加法,同样使用竖式。在做减法运算时,需要注意的是:需要有借位处理。

#include <iostream>
#include <cstring>int main() {int a[5005], b[5005], c[5005];int lena, lenb, lenc, i;char n[5005], n1[5005], n2[5005];std::memset(a, 0, sizeof(a));std::memset(b, 0, sizeof(b));std::memset(c, 0, sizeof(c));std::cin >> n1 >> n2; //输入被减数和减数lena = std::strlen(n1);lenb = std::strlen(n2);for(i=0; i<lena; i++) a[lena - i] = (int)n1[i] - '0';for(i=0; i<lenb; i++) b[lenb - i] = (int)n2[i] - '0'; //逆序存放排列i = 1;while(i <= lena || i <= lenb) {if(a[i] < b[i]) {c[i] = a[i] + 10 - b[i];a[i+1]--; //借位处理}else {c[i] = a[i] - b[i]; }i++;}lenc = i;while(c[lenc] == 0 && lenc > 1) { //如果最后一位是0,是需要输出的lenc--;   // 不输出首位0}for(i=lenc; i>=1; i--) std::cout << c[i];return 0;
}

高精度乘法 ×

类似加法,使用竖式。在做乘法时,同样也有进位。

分析 数组的下标变化规律,可以写出以下关系式:         

由此可见, 乘积有关,跟上次的进位有关,跟还原 的值有关,分析下标规律,有 :

#include <iostream>
#include <cstring>int main() {int a[105], b[105], c[10005];char n1[105], n2[105], lena, lenb, lenc, j, i, x;std::memset(a, 0, sizeof(a));std::memset(b, 0, sizeof(b));std::memset(c, 0, sizeof(c));std::cin >> n1 >> n2;lena = std::strlen(n1);lenb = std::strlen(n2);for(i=0; i<=lena-1; i++) a[lena - i] = n1[i] - 48; for(i=0; i<=lenb-1; i++) b[lenb - i] = n2[i] - 48; // 倒序储存for(i=1; i<=lena; i++) {x = 0;for(j=1; j<=lenb; j++) {c[i + j - 1] = c[i + j - 1] + x + a[i] * b[j];x = c[i + j - 1] / 10; // 进位c[i + j - 1] %= 10; // 剩余}c[i + lenb] = x; // 进位的数}lenc = lena + lenb;while(c[lenc] == 0 && lenc > 1) {lenc--; // 删除前导0}for(i=lenc; i>=1; i--) {std::cout << c[i];}  // 输出每一位std::cout << std::endl;return 0;
} 

除法 ÷

1)高精除以低精

做除法时,每一次的商值都在 0~9 之间,每次求得的余数连接以后的若干位得到新的被除数,继续做除法。因此,在做高精度除法时,要涉及到乘法运算和减法运算,还有移位处理。当然,为了程序简洁,可以避免高精度乘法,用 0~9 次循环减法取代得到商的值。采用按位相除法

#include <iostream>int main(){char n1[100];int a[100], c[100], lena, i, x = 0, lenc, b;std::memset(a, 0, sizeof(a));std::memset(c, 0, sizeof(c));std::cin >> n1 >> b;  lena = strlen(n1);for(i=1; i<=lena; i++) {a[i] = n1[i - 1] - '0'; //除法不需要逆序存放}//-------------------------初始化------------------------------for(i=1; i<=lena; i++) {c[i] = (a[i] + x * 10) / b;  // 算上上一位剩下的继续除x = (a[i] + 10 * x) % b; // 求余}lenc = 1;while(c[lenc] == 0 && lenc < lena) {lenc++;}for(i=lenc; i<lena; i++) std::cout << c[i];return 0;
}

2)高精除以高精

高精除以低精是对被除数的每一位(这里的"一位"包含前面的余数,以下都是如此)都除以除数,而高精除以高精则使用减法模拟除法,对被除数的每一位都减去除数,一直减到当前位置的数字(包含前面的余数)小于除数(由于每一位的数字小于10,所以对每一位最多进行10次运算),代码如下:

#include <cstdio>
#include <iostream>
#include <cstring>using namespace std;int a[50005], b[50005], c[50005], d;void init(int a[]) {char s[50005];cin >> s;a[0] = strlen(s);     // 字符串存储,表示位数    for (int i=1; i<=a[0]; i++) {a[i] = s[a[0]-i] - 48; // 正序储存}
}void print(int a[]) {          if (a[0] == 0) {cout << 0 << endl;return;  // 位数为0,输出0}for (int i=a[0]; i>=1; i--) {cout << a[i];  // 输出函数}cout << endl;return;
} int compare(int a[], int b[]) {   if (a[0] > b[0]) {return 1; // 被减数大于减数} if (a[0] < b[0]) {return -1; // 被减数小于减数}for (int i=a[0]; i>=1; i--) {    if (a[i] > b[i]) {return 1;} if (a[i] < b[i]) {return -1;}   // 位数相同,找到第一位不同的进行比较} return 0;
}void numcpy(int p[], int q[], int det) {for (int i=1; i<=p[0]; i++) {q[i+det-1] = p[i]; //复制p数组到q数组从det开始的地方}q[0] = p[0] + det - 1;
}void jian(int a[], int b[]) {      int flag = compare(a, b);       if (flag == 0)  {                    a[0] = 0;return;}if (flag == 1) {                for (int i=1; i<=a[0]; i++) {if (a[i] < b[i]) {            a[i+1]--;         a[i] += 10;}a[i] -= b[i];}while (a[0]>0 && a[a[0]]==0) {a[0]--;                 } return; }
}  // 高精减法void chugao(int a[], int b[], int c[]) {int tmp[50005];c[0] = a[0] - b[0] + 1;for (int i=c[0]; i>0; i--) {memset(tmp, 0, sizeof(tmp));  numcpy(b, tmp, i);// 清零while (compare(a, tmp) >= 0) {c[i]++;jian(a, tmp); // 用减法模拟        } }while (c[0] > 0 && c[c[0]] == 0) {c[0]--;}return;
}int main() {memset(a, 0, sizeof(a));memset(b, 0, sizeof(b));memset(c, 0, sizeof(c));init(a);init(b);chugao(a,b,c);print(c);    return 0;
}

如果这篇文章对你有帮助的话,请来个三连~~你们的支持是对我max(鼓 励)

C++ 算法 高精度(较详细.)相关推荐

  1. 【算法】超详细的遗传算法(Genetic Algorithm)解析

    转自:https://www.jianshu.com/p/ae5157c26af9 [算法]超详细的遗传算法(Genetic Algorithm)解析 00 目录 遗传算法定义 生物学术语 问题导入 ...

  2. 垃圾收集概述和垃圾收集算法(超详细介绍)

    文章目录 垃圾收集概述和垃圾收集算法(超详细介绍) 为什么我们还要去了解垃圾收集和内存分配 哪些内存需要回收 不需要回收的 需要回收的 方法区的回收 回收废弃常量 回收"不再被使用的类&qu ...

  3. 机器学习【期末复习总结】——知识点和算法例题(详细整理)

    机器学习[期末复习总结]--知识点和算法例题(详细整理) 1.什么是机器学习,什么是训练集,验证集和测试集?(摘自ML科普系列(一)) 机器学习: 对计算机一部分数据进行学习,然后对另外一些数据进行预 ...

  4. 排序算法 快速排序【详细步骤图解】

    排序算法 快速排序[详细步骤图解] 快速排序 主要思想 图解 第一轮分割序列 第二轮分割序列 --- 左子序列 小结 第三轮分割序列 --- 右子序列 C++实现 总结 快速排序 给定一个序列:22 ...

  5. 高精度算法——高精度减法

    介绍: 高精度减法也同加法一样,也是用于位数太大的运算,给你一个十几位的数你可能会做直接开个long long 的数据类型就解决了,但是给你一个100位的呢,1000位的呢,开long long 也不 ...

  6. 魔域私服服务器连接中断,魔域私服服务器中装备武器道具爆率相关算法及设置详细攻略分享...

    想必很多魔域私服玩家都比较好奇在游戏中各个高级怪物或者boss怪物的装备武器爆率是多少,其实这个问题不单单是玩家想要知道很多魔域私服gm也是非常想要知道的.在游戏里装备武器爆率绝对不是直接用一个百分比 ...

  7. A*算法(超级详细讲解,附有举例的详细手写步骤)

    背景:项目需要接触此算法,以下是一些自学成果,如有不足之处,欢迎指出,必虚心接受.做了一份PPT来汇报,此处直接使用自己PPT的截图.部分图片来源网络,如有侵权立马删除,以下博文仅作为学习笔记.后期又 ...

  8. 陈宝林《最优化理论与算法》超详细学习笔记 (八)————最优性条件

    陈宝林<最优化理论与算法>超详细学习笔记 (八)----最优性条件 无约束问题的极值条件 必要条件 二阶充分条件 充要条件 约束极值问题的最优性条件 不等式约束的一阶最优性条件 无约束问题 ...

  9. 陈宝林《最优化理论与算法》超详细学习笔记 (七)————第五章 运输问题

    陈宝林<最优化理论与算法>超详细学习笔记 (七)----第五章 运输问题 第1节 运输问题的数学模型 第2节 表上作业法 2.1 确定初始基可行解 2.2 最优解的判别 2.3 改进的方法 ...

  10. 陈宝林《最优化理论与算法》超详细学习笔记 (四)————第四章 对偶理论

    陈宝林<最优化理论与算法>超详细学习笔记 (四)----第四章 对偶理论 1. 对偶问题的提出 2. 线性规划的对偶理论 2.1 原问题与对偶问题的关系 2.2 对偶问题的基本性质 3. ...

最新文章

  1. 4月全球操作系统市场份额:Win 7份额连续4月上涨
  2. Windows 技术篇 - 电脑秒速关机设置方法,注册表修改3个缓冲等待时间
  3. 曲线的生成算法实现_PCGPlanet1-地形生成算法简介
  4. vue-cli 3.0 跨域请求代理
  5. 绝地求生服务器维护内容,绝地求生最新更新维护几点开始? 绝地求生10.30更新维护内容...
  6. ORM框架之Mybatis(五)mybatis生成器配置文件说明以及生成的类的说明
  7. 为vs2008添加Mobile Web Forms模板
  8. mysql图书管理系统设计答辩_基于微信的图书管理系统毕业论文+任务书+开题报告+答辩PPT+前后台(Java+Mysql)源码及数据库文件...
  9. 《我想进大厂》之MQ夺命连环11问
  10. 360浏览各模式及内核的使用说明
  11. 计算机图形学之绘制旗子
  12. Anaconda下安装Tensorflow和Keras的安装教程
  13. 城市交通大数据及智能应用
  14. 使用RRDTOOL进行绘图
  15. H5+CSS初级试题
  16. Pin API INS
  17. 程序员的“三大死穴”
  18. 电脑安装Win10 + Linux 双系统
  19. aise TypeError(f“{method_name}: `{super_param.name}` must be present“)
  20. 汇聚150万开发者,华为云致力于成为最佳应用构建平台

热门文章

  1. 什么是物理路径、相对路径、绝对路径、根目录------java初学者学习笔记
  2. fiddler,iphone安装证书后还是无法访问HTTPS网站
  3. 程序员初入公司:10大经验让你能力提升20倍! 1
  4. Mysql出现问题:如何查询插件,安装插件解决方案
  5. Linux c/c++编程--feof函数
  6. 个人认为最佳模板制作方案
  7. DQN(deep Q-network)算法简述
  8. 我用代码做过的有趣的东西
  9. linux系统gcc编译.c文件没有标准库解决
  10. 使用python进行数据清洗及ols回归分析