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

这篇具有很好参考价值的文章主要介绍了大数计算(大数加法/大数乘法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

❤️‍🔥专栏系列:线性代数,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的值为0
            int x2=end2>=0?num2[end2]-'0':0;//x2就是获取一个数据end2下标的数据,之所以会减'0',在num存储的数据是字符,只要减'0'才是对应的整数。end2>=0?num2[end2]-'0':0如果num2数据遍历完了,就会让x2的值为0
            int ret=x1+x2+next;//计算两个数据对应位之和

            next=ret/10;//两个数据对应位之和大于等于10,就会产生进位
            ret=ret%10;//两个数据对应位之和小于10

            str+=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的数据传递strN
    int n=0;//n是存储的是num2整形的数字,例如num2=“123”,n=123
    for(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的值为0
                int x2=strN[end2]-'0';//x2就是获取一个数据end2下标的数据,之所以会减'0',在strN存储的数据是字符,只要减'0'才是对应的整数。
                int ret=x1+x2+next;//计算两个数据对应位之和

                next=ret/10;//两个数据对应位之和大于等于10,就会产生进位
                ret=ret%10;//两个数据对应位之和小于10

                str+=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++;//标志+1
       end2--;//让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

 🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸   文章来源地址https://www.toymoban.com/news/detail-638697.html

到了这里,关于大数计算(大数加法/大数乘法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • nowcoder NC10 大数乘法

    题目链接:  https://www.nowcoder.com/practice/c4c488d4d40d4c4e9824c3650f7d5571?tpId=196tqId=37177rp=1ru=/exam/companyqru=/exam/companysourceUrl=%2Fexam%2Fcompanydifficulty=undefinedjudgeStatus=undefinedtags=title= 目录 题目描述: 答案: 详解:  以字符串的形式读入两个数字,编写一个函数计算它们的乘积,以字符串形

    2024年02月09日
    浏览(16)
  • Verilog|有无符号加法与乘法运算

    一、无符号: 直接运算 二、有符号与无符号: 强制当作无符号运算 如c=a+b,a、b四位,c五位,计算时Verilog会将a和b扩展到五位再做加法,如果ab中有无符号数,则展宽会按照无符号数来,就是高位补0,因此有符号数结果将不正确。 解决:$signed(),c=a+$signed(b),扩展会按照有符

    2024年02月14日
    浏览(30)
  • 稀疏矩阵的加法和乘法(三元组)

    三元组方法: 主要的特点就是最后的结果矩阵均由三元组的形式来表达,调用函数再以矩阵形式输出 (1)稀疏矩阵加法 (下图参考懒猫老师《数据结构》课程相关笔记)  这里与普通矩阵加法不同的是,稀疏矩阵的三元组在加法计算时, 如果两个矩阵中的元素相加不为0时

    2024年01月17日
    浏览(33)
  • 离散数学16__矩阵的加法、乘法

    常见的矩阵有 4*4 一 矩阵的加法,就是一个矩阵的第几行第几列,与 另一个矩阵相同的第几行第几列,相加。 也就是说,矩阵相加是相同位置加一下。   得到一个新矩阵。   二 矩阵的乘法 这里以矩阵的平方M² 是一个新矩阵,这个矩阵的mij 等于矩阵M的第i 行 和第j列对应

    2024年02月10日
    浏览(23)
  • 高精度加法,减法,乘法,除法(上)(C语言)

    前言 本篇内容介绍加法和减法,如果想看乘法和除法就点这里-高精度乘法,除法 加,减,乘,除这些运算我们自然信手捏来,就拿加法来说,我们要用c语言编程算a+b的和,只需让sum = a+b即可,可是这是局限的,我们都知道int的表示的最大值为2147483647(32位和64位机器)。但

    2024年02月03日
    浏览(29)
  • 高精度加法,减法,乘法,除法(下)(C语言)

    前言 上一篇博客我们分享了高精度加法,减法,这一期我将为大家讲解高精度乘法和高精度除法。那让我们开始吧! 对加法和减法感兴趣的话就点我 让我们想想我们平时做数学时遇见乘法是怎么做的。以下图为例。 高精度乘法也是这样的一个思路,首先我们先把a和b的值储存

    2024年02月04日
    浏览(51)
  • 矩阵与向量的运算:矩阵的加法、数乘与乘法

    作者:禅与计算机程序设计艺术 \\\"矩阵与向量的运算\\\"是机器学习领域的一个基础课。在实际应用中,许多算法都需要涉及到矩阵运算。理解并掌握这种运算对于解决复杂的问题和优化模型性能至关重要。本文将带您快速了解矩阵的概念,以及如何进行矩阵运算。 \\\"行列式\\\"是指

    2024年02月11日
    浏览(28)
  • 稀疏矩阵(三元组)的创建,转置,遍历,加法,减法,乘法。C实现

    1.创建。 可以直接赋值字符串,但是为0的元素也要依次赋值,比较麻烦,但是容易理解也能实现。 其次也可以构思三元组赋值,只赋值非零元素和它的行,列数,在打印时进行if判断,没有赋值的就输出0,这样比较简单。 创建结构体时,一个矩阵需要有它的行总数和列总数

    2024年02月02日
    浏览(42)
  • PTA 习题3.6 一元多项式的乘法与加法运算

    设计函数分别求两个一元多项式的乘积与和。 输入格式: 输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。 输出格式: 输出分2行,分别以指数递降方式输出乘积多项式

    2024年02月07日
    浏览(29)
  • excel中怎么用乘法、加法来替代AND和OR函数

    你可以使用乘法和加法来替代Excel中的AND和OR函数,虽然这样做可能会增加公式的复杂度,但在某些情况下是可行的。 1. 使用乘法替代AND函数: AND函数用于判断一系列条件是否同时成立,如果所有条件都为TRUE,则返回TRUE,否则返回FALSE。你可以使用乘法来实现类似的效果,因

    2024年04月26日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包