大数计算(大数加法/大数乘法)

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

概念

大数加法

加法原理

编程分析

大数乘法

乘法原理

编程分析

(1)累加法

(2)直接乘积法

效率对比

结果


概念

计算机发明的初衷就是解决以人类计算能力无法有效解决的问题,这类问题包括反复多次的复杂运算也包括天文级数字的运算,但就c语言的初步学习可以发现,不论是int还是float乃至更大的unsigned long long int和double形式的数据都是有极限的。一般形式的数据里最大的整型是unsigned long long int,极限为18446744073709551615,是10^19次方的数量级,就日常生活的问题可能足够了,但以计算机的计算能力而言远远不够。

例如64位下的一个整形为例,一个整形四个字节,32bit位,存储的最大数据为4294967296,然而4294967295只有10位,如果字符数组存储只需两个字节,而且数组长度可以非常大。所以用字符数组存储数据,模拟计算数据去解决天文级数字的运算等难题。

大数加法

加法原理

进行计算之前,我们先明白加法的原理

例如 12+9=21

2+9+0(余数)=11

余数:1

取模:1

1+1(余数)=2

余数:0

取模:2

所以等于21

转化为编程思想:

例如 12+9=21

str:string的对象,next:表示进位

next=0;

str:”"

2+9+next=11

next=1

str:”1”

1+0+next=2

next=0

str:”12”

最后逆置一下str,str:”21"

编程分析

string addStrings(string num1, string num2)//num1存储第一个数据,num2存储第二个数据
{int end1=num1.size()-1,end2=num2.size()-1;//这里我们获取每个数据的最后一位数的下标,因为我们进行计算,都是从最后一位数计算的int next=0;//表示的进位string str;//存储两个数据之和的对象while(end1>=0||end2>=0)//值得注意的是,我们对两个数据相加,是对每一个数据对应位相加,但如果一个数据min的位数少于另一位max数据,我们不能停止相加,只是max多余的位都加0而已,所以这里的循环结束的条件是,两个数据遍历完才停止。{//我们存储数据是用字符数组,计算数据还是以整形计算int x1=end1>=0?num1[end1]-'0':0;//x1就是获取一个数据end1下标的数据,之所以会减'0',在num存储的数据是字符,只要减'0'才是对应的整数。end1>=0?num1[end1]-'0':0如果num1数据遍历完了,就会让x1的值为0int x2=end2>=0?num2[end2]-'0':0;//x2就是获取一个数据end2下标的数据,之所以会减'0',在num存储的数据是字符,只要减'0'才是对应的整数。end2>=0?num2[end2]-'0':0如果num2数据遍历完了,就会让x2的值为0int ret=x1+x2+next;//计算两个数据对应位之和next=ret/10;//两个数据对应位之和大于等于10,就会产生进位ret=ret%10;//两个数据对应位之和小于10str+=ret+'0’;//存储两个数据对应位之和小于10的部分end1--,end2—;//让两个数据的下标往前移动}reverse(str.begin(),str.end());//因为str存储的数据是相反的,所以需要逆置一下,reverse是string类里的逆置函数if(next==1)//就是两个数据相加时,最后一位也可能产生进位,例如:98+3,str里只保存了01,而最高位的1还没有保存就跳出循环了,所以在这里,可以将进位头插在str中str.insert(0,1,'1’);//在str下标为0处插入1个’1'return str;
}

大数乘法

乘法原理

进行计算之前,我们先明白乘法的原理

例如 25*12=300

5*2+0(余数)=10

取余:1

取模:0

2*2+1(余数)=5

取余:0

取模:5

个位乘积:50

5*1+(余数)=5

取余:0

取模:5

2*1+(余数)=2

取余:0

取模:2

十位乘积:25

总积:25*10+50=300

转化为编程思想:

例如 25*12=300

strN:string的对象,str:string的对象,next:表示进位

next=0

str=“”

strN=“0”

5*2+next=10

next=1

str=“0”

2*2+next=5

next=0

str=“05”

strN=strN+“50”

next=0

str=“”

5*1+next=5

next=0

str=“5”

2*1+next=2

next=0

str=“52”

strN=strN+”250”

strN=“300"

编程分析

(1)累加法

其实,乘法可以转换为加法,例如25*12,我们可以将25累加12次,这样也能达到乘法的效果。

缺陷:效率低

string multiply_1(string num1, string num2)//num1存储第一个数据,num2存储第二个数据
{string strN=num1;//strN时记录乘积总和的对象,我们将num2的数据传递strNint n=0;//n是存储的是num2整形的数字,例如num2=“123”,n=123for(int i=0,j=pow(10,num2.size()-1);i<num2.size();i++,j/=10)//这个循环就是转换过程{n+=(num2[i]-'0')*j;}n-=1;//因为我们开始在strN中存储了num2的数据,所以我们在家的过程需要少累加一次while(n—)//通过循环开始累加{//我们存储数据是用字符数组,计算数据还是以整形计算string str;//str存储的是一次累加的数据int end1=num1.size()-1,end2=strN.size()-1;//这里我们获取每个数据的最后一位数的下标,因为我们进行计算,都是从最后一位数计算的int next=0;//进位while(end1>=0||end2>=0){int x1=end1>=0?num1[end1]-'0':0;//x1就是获取一个数据end1下标的数据,之所以会减'0',在num存储的数据是字符,只要减'0'才是对应的整数。end1>=0?num1[end1]-'0':0如果num1数据遍历完了,就会让x1的值为0int x2=strN[end2]-'0';//x2就是获取一个数据end2下标的数据,之所以会减'0',在strN存储的数据是字符,只要减'0'才是对应的整数。int ret=x1+x2+next;//计算两个数据对应位之和next=ret/10;//两个数据对应位之和大于等于10,就会产生进位ret=ret%10;//两个数据对应位之和小于10str+=ret+'0';//存储两个数据对应位之和小于10的部分end1--,end2--;//让两个数据的下标往前移动}reverse(str.begin(),str.end());//因为str存储的数据是相反的,所以需要逆置一下,reverse是string类里的逆置函数if(next==1)//就是两个数据相加时,最后一位也可能产生进位,例如:98+3,str里只保存了01,而最高位的1还没有保存就跳出循环了,所以在这里,可以将进位头插在str中str.insert(0,1,'1');//在str下标为0处插入1个’1'strN=str;//将str的数据传递给strN}return strN;
}

(2)直接乘积法

直接通过,乘法的计算原理进行计算

string multiply(string num1, string num2)//num1存储第一个数据,num2存储第二个数据
{int end2=num2.size()-1;//这里我们获取每个数据的最后一位数的下标,因为我们进行计算,都是从最后一位数计算的string strN("0”);//strN是记录乘积总和的对象,初始值为’0'int flag=-1;//是一个标志while(end2>=0&&(num1[0]!='0'&&num2[0]!='0’))//只要遍历完num2中的数据就结束运算,还有如果num1和num2中只要有一个为’0'就结束运算{int end1=num1.size()-1;//这里我们获取每个数据的最后一位数的下标,因为我们进行计算,都是从最后一位数计算的string str;//记录每次num1中的数据和num2中每一位值的乘积int next=0;//进位int x2=num2[end2]-'0’;//x2就是获取一个数据end2下标的数据,之所以会减'0',在strN存储的数据是字符,只要减'0'才是对应的整数。while(end1>=0)//遍历num1中的数据{int x1=num1[end1]-'0';//x1就是获取一个数据end1下标的数据,之所以会减'0',在num存储的数据是字符,只要减'0'才是对应的整数。int ret=x1*x2+next;//计算num1每一位和num1每一位的乘积next=ret/10;//num1每一位和num1每一位的乘积大于10,就会产生进位ret=ret%10;//num1每一位和num1每一位的乘积小于10的值str+=ret+'0’;//存储num1每一位和num1每一位的乘积小于10的值end1—;//让num1数据的下标往前移动}flag++;//标志+1end2--;//让num2数据的下标往前移动reverse(str.begin(),str.end());//因为str存储的数据是相反的,所以需要逆置一下,reverse是string类里的逆置函数int count=flag;//传递标志的值while(count—)//num2每一位值和num1数据乘积等级是不同的,num1第一位是个位,第二位是位,第三位是千位…,所以str存储数据是应该加上对应数目的’0'{str+='0';}char ch=next+'0';if(next!=0)//就是num2每一位值和num1数据乘积时,最后一位也可能产生进位,例如:98*3,str里只保存了94,而最高位的2还没有保存就跳出循环了,所以在这里,可以将进位头插在str中str.insert(0,1,ch);strN=addStrings(strN, str);//将num2每一位值和num1数据乘积累加给strN,addStrings是我们前面提到的大数加法}return strN;
}

效率对比

同时计算999999*999999,看所需要的时间

#include<iostream>
#include<cmath>
using namespace std;
string multiply_1(string num1, string num2)
{string strN=num1;int n=0;for(int i=0,j=pow(10,num2.size()-1);i<num2.size();i++,j/=10){n+=(num2[i]-'0')*j;}n-=1;while(n--){string str;int end1=num1.size()-1,end2=strN.size()-1;int next=0;while(end1>=0||end2>=0){int x1=end1>=0?num1[end1]-'0':0;int x2=strN[end2]-'0';int ret=x1+x2+next;next=ret/10;ret=ret%10;str+=ret+'0';end1--,end2--;}reverse(str.begin(),str.end());if(next==1)str.insert(0,1,'1');strN=str;}return strN;
}
//25
// 3
//next=0
//5*3+next=15
//next=1
//str:5
//2*3+next=7
//str:57
//75
string addStrings(string num1, string num2)
{int end1=num1.size()-1,end2=num2.size()-1;int next=0;string str;while(end1>=0||end2>=0){int x1=end1>=0?num1[end1]-'0':0;int x2=end2>=0?num2[end2]-'0':0;int ret=x1+x2+next;next=ret/10;ret=ret%10;str+=ret+'0';end1--,end2--;}reverse(str.begin(),str.end());if(next==1)str.insert(0,1,'1');return str;
}
string multiply(string num1, string num2)
{int end2=num2.size()-1;string strN("0");int flag=-1;while(end2>=0&&(num1[0]!='0'&&num2[0]!='0')){int end1=num1.size()-1;string str;int next=0;int x2=num2[end2]-'0';while(end1>=0){int x1=num1[end1]-'0';int ret=x1*x2+next;next=ret/10;ret=ret%10;str+=ret+'0';end1--;}flag++;end2--;reverse(str.begin(),str.end());int count=flag;while(count--){str+='0';}char ch=next+'0';if(next!=0)str.insert(0,1,ch);strN=addStrings(strN, str);}return strN;
}
int main()
{string s1,s2;cin>>s1>>s2;size_t begin_1=clock();cout<<"累加法的值:"<<multiply_1(s1, s2)<<endl;size_t end_1=clock();cout<<"累加法的时间:"<<end_1-begin_1<<"10^-3ms"<<endl;size_t begin_2=clock();cout<<"直接乘积法的值:"<<multiply(s1, s2)<<endl;size_t end_2=clock();cout<<"直接乘积法的时间:"<<end_2-begin_2<<"10^-3ms"<<endl;return 0;
}

结果

结果:

999999 999999

累加法的值:999998000001

累加法的时间:51161310^-3ms

直接乘积法的值:999998000001

直接乘积法的时间:1210^-3ms

 🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/29809.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言使用库函数实现大小写字母转换

功能&#xff1b;多行输入&#xff0c;输入大写字母&#xff0c;返回相应的小写字母&#xff1b;输入小写字母&#xff0c;返回相应的大写字母 需要用到的库函数&#xff1a; islower&#xff08;&#xff09; -- 判断是否为小写&#xff0c;是&#xff0c;返回非0&#xff0c;…

leetcode870. 优势洗牌(java)

优势洗牌 leetcode870. 优势洗牌题目描述双指针 排序代码 滑动窗口 leetcode870. 优势洗牌 难度 - 中等 leetcode870. 优势洗牌 题目描述 给定两个长度相等的数组 nums1 和 nums2&#xff0c;nums1 相对于 nums2 的优势可以用满足 nums1[i] > nums2[i] 的索引 i 的数目来描…

博客网站添加复制转载提醒弹窗Html代码

网站如果是完全禁止右键&#xff08;复制、另存为等&#xff09;操作&#xff0c;对用户来说体验感会降低&#xff0c;但是又不希望自己的原创内容直接被copy&#xff0c;今天飞飞和你们分享几行复制转载提醒弹窗Html代码。 效果展示&#xff1a; 复制以下代码&#xff0c;将其…

matplotlib 笔记:基本用法

1 axis 1.0 对比原始图像 import numpy as np import matplotlib.pyplot as plt xrange(5) yrange(10,20,2) plt.plot(x,y) 1.1 plt.axis(equal) x轴和y轴单位长度相同 import numpy as np import matplotlib.pyplot as plt plt.axis(equal) xrange(5) yrange(10,20,2) pl…

【iOS】autoreleasepool

来说一下最近在了解的autoreleasepool吧&#xff0c;我们可能平时书写过许多脑残代码&#xff0c;其有很多的缺陷但是我们可能当时学的比较浅就也不太了解&#xff0c;就像下面这样的&#xff1a; for (int i 0; i < 1000000; i) {NSNumber *num [NSNumber numberWithInt…

SAP MIGO 移动原因维护

在OMJJ中维护 在OMJJ中&#xff0c;选择你要维护的移动类型&#xff0c;在“对话结构”中选择“移动原因”&#xff0c;可以修改和添加了。

vb+SQL航空公司管理系统设计与实现

航空公司管理信息系统 一个正常营运的航空公司需要管理所拥有的飞机、航线的设置、客户的信息等,更重要的还要提供票务管理。面对各种不同种类的信息,需要合理的数据库结构来保存数据信息以及有效的程序结构支持各种数据操作的执行。 本设计讲述如何建立一个航空公司管理信…

Java用方法实现登录名和密码的校验

Java用方法实现登录名和密码的校验 需求分析代码实现小结Time 需求分析 系统正确的登录名和密码是:学习/123&#xff0c;请在控制台开发一个登录界面&#xff0c;接收用户输入的登录名和密码&#xff0c;判断用户是否登录成功&#xff0c;登录成功后展示:“欢迎进入系统!”&…

C# OpenCvSharp 去水印 图像修复

效果 项目 VS2022.net4.8OpenCvSharp4 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; usi…

Improved Deep Metric Learning with Multi-class N-pair Loss Objective

Improved Deep Metric Learning with Multi-class N-pair Loss Objective 来源&#xff1a; NIPS’2016NEC Laboratories America 文章目录 Improved Deep Metric Learning with Multi-class N-pair Loss ObjectiveDistance Metric LearningDeep Metric Learning with Multip…

时间复杂度空间复杂度相关练习题

1.消失的数字 【题目】&#xff1a;题目链接 思路1&#xff1a;排序——》qsort快排——》时间复杂度O&#xff08;n*log2n&#xff09; 不符合要求 思路2&#xff1a;&#xff08;0123...n)-(a[0]a[1][2]...a[n-2]) ——》 时间复杂度O&#xff08;N&#xff09;空间复杂度…

Promise和async/await的使用及其应用场景

Promise 和 async/await 都是用于处理 JavaScript 异步操作的机制&#xff0c;它们在处理异步代码和处理回调地狱方面提供了更清晰和可维护的方式。 Promise 使用及原理&#xff1a; Promise 是一种处理异步操作的方式&#xff0c;它可以在异步操作完成时进行响应&#xff0c…

(Python)计算R方

计算R方是统计学中的一项重要任务&#xff0c;它可以评估一个模型的拟合程度 Python是一种广泛使用的编程语言&#xff0c;也是计算R方的一个强大工具 import numpy as np from sklearn.metrics import r2_score # 生成一些模拟数据 y_true np.array([1, 2, 3, 4, 5]) y_pred …

第十七章 定义 HL7 的 DTL 数据转换 - 空映射代码

文章目录 第十七章 定义 HL7 的 DTL 数据转换 - 空映射代码空映射代码 第十七章 定义 HL7 的 DTL 数据转换 - 空映射代码 空映射代码 有些 HL7 应用程序使用空映射约定。根据此约定&#xff0c;源应用程序可以发送一个由两个连续双引号字符 ("") 组成的字段&#x…

Java Api实现Elasticsearch的滚动查询

解决ES每次只能查询一万条数据的问题 Overridepublic List<ESHandleDto> getVisitorsNum(String startTime, String endTime, String schoolName, String typeFunction) throws IOException {List<ESHandleDto> esHandleDtos new ArrayList<>();SearchReque…

spring cloud智慧工地源码(项目端+监管端+数据大屏+APP)

spring cloud智慧工地源码&#xff08;项目端监管端数据大屏APP&#xff09; 系统功能介绍 【智慧工地PC项目端功能总览】 一.项目人员管理 包括&#xff1a;信息管理、信息采集、证件管理、考勤管理、考勤明细、工资管理、现场统计、WIFI教育、工种管理、分包商管理、班组管…

STM32 HAL 驱动PM2.5传感器(GP2Y10AU气体检测模块)

目录 1、简介 2、CubeMX初始化配置 2.1 基础配置 2.1.1 SYS配置 2.1.2 RCC配置 2.2 ADC外设配置 2.3 串口外设配置 2.4 项目生成 3、KEIL端程序整合 3.1 串口重映射 3.2 ADC数据采集 3.3 主函数代 3.4 效果展示 1、简介 本文通过STM32F103C8T6单片机通过HAL库方式对G…

RxJava的前世【RxJava系列之设计模式】

一. 前言 学习RxJava&#xff0c;少不了介绍它的设计模式。但我看大部分文章&#xff0c;都是先将其用法介绍一通&#xff0c;然后再结合其用法&#xff0c;讲解其设计模式。这样当然有很多好处&#xff0c;但我个人觉得&#xff0c;这种介绍方式&#xff0c;对于没有接触过Rx…

Qt 使用QLabel的派生类实现QLabel的双击响应

1 介绍 在QLabel中没有双击等事件响应&#xff0c;需要构建其派生类&#xff0c;自定义信号(signals)、重载事件函数(event)&#xff0c;最后在Qwidget中使用connect链接即可&#xff0c;进而实现响应功能。 对于其余没有需求事件响应的QObject同样适用。 此外&#xff0c;该功…

【HDFS】客户端读某个块时,如何对块的各个副本进行网络距离排序?

本文包含如下内容: ① 通过图解+源码分析/A1/B1/node1和 /A1/B2/node2 这两个节点的网络距离怎么算出来的 ② 客户端读文件时,副本的优先级。(怎么排序的,排序规则都有哪些?) ③ 我们集群发现的一个问题。 客户端读时,通过调用getBlockLocations RPC 获取文件的各个块。…