本文为大大维原创,最早于博客园发表,转载请注明出处!!!

一、概述

  C/C++中的int类型能表示的范围是-2E31-2E31–1。unsigned类型能表示的范围是0-2E32–1,即 0-4294967295。所以,int和unsigned类型变量,都不能保存超过10位的整数。有时我们需要参与运算的数,可能会远远不止10 位,例如,可能需要保留小数点后面100位(比如求π的值),那么,即便使用能表示很大数值范围的double变量,但是由于double变量只有64位,所以还是不可能达到精确到小数点后面100位这样的精度。double变量的精度也不足以表示一个100位的整数。一般我们称这种基本数据类型无法表示的整数为大数。如何表示和存放大数呢?在c语言下,我们可以用数组存放和表示大整数,一个数组元素,存放大数中的一位。而在c++中,使用标准库的string类型,使得大数问题的计算更加实用(没有最大值的限制),更加灵活(输入更加简洁方便),更加简单(可以方便的处理小数之间的运算)。

二、算法原理简单描述:

看如下大整数的加法运算:

  answer每一位都是num1、num2和carry的和,因此,我们在输入加数和被加数的string之后,可以将内容进行一次反转,这样,answer[i]=num1[i]+num2[i]+carry[i-1]。反转的一个重要的原因是可以方便的将向前的进位和运算变为向后的进位运算,有利于充分发挥string的特点。在这里,我们可以使用<algorithm>头文件下的reverse()函数方便的实现string的内容反转。当运算完毕后,反转回来即可。

  当加入小数点后,我们就需要考虑一些额外的问题--小数点的位置问题,笔者在此采用了如下的策略:将输入内容格式检查之后(使用了cctpe头文件),将一个数分为小数部分和整数部分,然后先运算小数部分,将得到的carry最后和整数部分一起运算,最后将两部分的和拼接在一起。

  对于大数的减法问题,基本上是大数加法的一个逆运算过程,笔者不在细讲,看源代码就可以很容易的理解。

三、程序代码:

 /*
大数的运算1--加法:
利用C++ string实现任意长度正小数、整数之间的加减法
作者:大大维
2017/5/5
*/
#include<iostream>
#include<string>
#include<cctype>
#include<algorithm>
using namespace std;
string sum(string,string,string,string);
string sub(string,string,string,string);
int main()
{
string num1,num2;
cout<<"Input num1 , num2:"<<endl;
cin>>num1>>num2;
string num11,num12,num21,num22;
//输入检查
//是否是小数的标志
bool num1Flag=false,num2Flag=false;
for(auto c:num1)
{
//由数字或者数字加一个.组成
if(!isdigit(c)||num1.empty())
{
if(c=='.'&&!num1Flag)
{
num1Flag=true;
}
else
{
cout<<"num1: Please input correct form!!!"<<endl;
return ;
}
}
}
for(auto c:num2)
{
if(!isdigit(c)||num2.empty())
{
if(c=='.'&&!num2Flag)
{
num2Flag=true;
}
else
{
cout<<"num2: Please input correct form!!!"<<endl;
return ;
}
}
} //字符串分割{整数部分和小数部分)
if(num1Flag)//如果是小数
{
int i=;
while(i!=num1.size()&&num1[i]!='.')
{
num11+=num1[i];
++i;
}
while(++i!=num1.size())
{
num12+=num1[i];
}
//用于.XXX或XXX.型输入的控制
if(num11.empty())
num11+='';
if(num12.empty())
num12+='';
}
else//如果是整数
{
num11=num1;
num12+='';
}
if(num2Flag)//如果是小数
{
int i=;
while(i!=num2.size()&&num2[i]!='.')
{
num21+=num2[i];
++i;
}
while(++i!=num2.size())
{
num22+=num2[i];
}
//用于.XXX或XXX.型输入的控制
if(num21.empty())
num21+='';
if(num22.empty())
num22+='';
}
else//如果是整数str
{
num21=num2;
num22+='';
} cout<<"The Sum result = "<<sum(num11,num12,num21,num22)<<endl;
cout<<"The Sub result = "<<sub(num11,num12,num21,num22)<<endl;
} //加法 较长的整数部分 较长的小数部分 较短的整数部分 较短的小数部分
string sum(string strLong1,string strLong2,string strShort1,string strShort2)
{
//小数部分计算
if(strLong2.size()<strShort2.size())
{
string strTemp=strLong2;
strLong2=strShort2;
strShort2=strTemp;
}
//补0
for(int i=strShort2.size(); i<strLong2.size(); ++i)
strShort2+='';
//反转字符串
reverse(strLong2.begin(),strLong2.end());
reverse(strShort2.begin(),strShort2.end());
//小数部分进行加法计算
string strRes2(strLong2.size(),'');
int carry=;//进位
for(int i=; i!=strLong2.size(); ++i)
{
int a=strShort2[i]-'',b=strLong2[i]-'';
a=a+b+carry;
carry=a/;
strRes2[i]=(a%)+'';
}
//反转回来
reverse(strRes2.begin(),strRes2.end()); //整数部分计算
if(strLong1.size()<strShort1.size())
{
string strTemp=strLong1;
strLong1=strShort1;
strShort1=strTemp;
}
//反转字符串
reverse(strLong1.begin(),strLong1.end());
reverse(strShort1.begin(),strShort1.end()); string strRes1(strLong1.size(),'');
for(int i=; i!=strShort1.size(); ++i)
{
int a=strShort1[i]-'',b=strLong1[i]-'';
a=a+b+carry;
carry=a/;
strRes1[i]=(a%)+'';
}
for(int i=strShort1.size(); i!=strLong1.size(); ++i)
{
int b=strLong1[i]-'';
b+=carry;
carry=b/;
strRes1[i]=b%+'';
}
if(carry)
{
strRes1+=(carry+'');
}
//反转回来
reverse(strRes1.begin(),strRes1.end()); //合并整数部分和小数部分
string strRes=strRes1+'.'+strRes2;
return strRes;
} //减法 被减数的整数部分 被减数的小数部分 减数的整数部分 减数的小数部分
string sub(string strBjs1,string strBjs2,string strJs1,string strJs2)
{
//小数部分进行减法计算
int cntTemp=strBjs2.size()-strJs2.size();
//补0
if(cntTemp<=)
{
for(int i=cntTemp;i!=;++i)
{
strBjs2+='';
}
}
else
{
for(int i=cntTemp;i!=;--i)
{
strJs2+='';
}
} //反转字符串
reverse(strBjs2.begin(),strBjs2.end());
reverse(strJs2.begin(),strJs2.end());
string strRes2(strBjs2.size(),'');
int carry=;//进位
for(int i=; i!=strBjs2.size(); ++i)
{
int a=strBjs2[i]-'',b=strJs2[i]-'';
a=a-b-carry;
if(a>=)
{
carry=;
strRes2[i]=a+'';
}
else
{
carry=;
strRes2[i]=a++'';
}
}
//反转回来
reverse(strRes2.begin(),strRes2.end()); //整数部分进行减法计算
//反转字符串
reverse(strBjs1.begin(),strBjs1.end());
reverse(strJs1.begin(),strJs1.end());
string strRes1(strBjs1.size(),'');
for(int i=;i!=strJs1.size();++i)
{
int a=strBjs1[i]-'',b=strJs1[i]-'';
a=a-b-carry;
if(a>=)
{
carry=;
strRes1[i]=a+'';
}
else
{
carry=;
strRes1[i]=a++'';
}
}
for(int i=strJs1.size();i!=strBjs1.size();++i)
{
int a=strBjs1[i]-'';
a=a-carry;
if(a>=)
{
carry=;
strRes1[i]=a+'';
}
else
{
carry=;
strRes1[i]=a++'';
}
}
if(carry)//此时除数比被除数大,结果为负数
{
return "*";
}
//反转回来
reverse(strRes1.begin(),strRes1.end()); //清楚冗余0
string strTemp;
cntTemp=;
for(int i=;strRes1[i]=='';++i)++cntTemp;
for(int i=cntTemp;i!=strRes1.size();++i)
strTemp+=strRes1[i];
strRes1=strTemp;
//合并整数部分和小数部分
string strRes=strRes1+'.'+strRes2;
return strRes;
}

四、运行结果截图:

说明1:此处有一定的容错性,可以处理(.X或X.型的数据)

说明2:(*)表示结果为负数,不再处理

说明3:对输出格式统一控制为小数类型

[c++]大数运算---利用C++ string实现任意长度正小数、整数之间的加减法的更多相关文章

  1. [c++]大数运算1---利用C++ string实现任意长度正小数、整数之间的加减法

    一.概述 本文属于大大维原创,未经笔者本人允许,严禁转载!!! C/C++中的int类型能表示的范围是-2E31-2E31–1.unsigned类型能表示的范围是0-2E32–1,即 0-429496 ...

  2. 求任意长度数组的最大值(整数类型)。利用params参数实现任意长度的改变。

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. 收藏的一段关于java大数运算的代码

    收藏的一段关于java大数运算的代码: package study_02.number; import java.math.BigDecimal; import java.math.BigIntege ...

  4. [PKU2389]Bull Math (大数运算)

    Description Bulls are so much better at math than the cows. They can multiply huge integers together ...

  5. java 大数运算[转]

    用JAVA 实现算术表达式(1234324234324 + 8938459043545)/5 + 343434343432.59845 因为JAVA语言中的long 定义的变量值的最大数受到限制,例如 ...

  6. A+B大数运算

    基础加法大数运算: [https://vjudge.net/problem/HDU-1002] 题目: 输入两个长度不超过1000的整数求出sum. 思路: 由于数字很大不能直接加,用字符串形式输入, ...

  7. HOJ 2148&POJ 2680(DP递推,加大数运算)

    Computer Transformation Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4561 Accepted: 17 ...

  8. 九度OJ 1119:Integer Inquiry(整数相加) (大数运算)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:679 解决:357 题目描述: One of the first users of BIT's new supercomputer was ...

  9. lua实现大数运算

    lua实现的大数运算,代码超短,眼下仅仅实现的加减乘运算 ------------------------------------------------ --name: bigInt --creat ...

随机推荐

  1. angular配置路由/子页面+vue配置路由/子页面

    1.在vue.js中组件可以复用,然后最近配置了几个子页面 在 这个文件中配置路由,子页面的配置跟其他一样,只不过path不同.   routes: [     { path: '/',       ...

  2. 软件工程——四则运算py(我小学的时候怎么没用过这东西?)

    题目:实现一个自动生成小学四则运算题目的命令行程序 github地址:https://github.com/ILTHEW/wc.git 主编:黄晖朝3116005178 助手:朱健栋311600520 ...

  3. windows WebStorm常用快捷键记录,常用的都在这儿找扒

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Webstorm version 2018.2  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Ctrl + Shift + ...

  4. gitlab安装随记

    gitlab安装 配置yum源 sudo vim /etc/yum.repos.d/gitlab-ce.repo 按照网上别人的例子,修改为清华的源 [gitlab-ce] name=Gitlab C ...

  5. 通讯录管理系统(C语言)

    /* * 对通讯录进行插入.删除.排序.查找.单个显示功能 */ #include <stdio.h> #include <malloc.h> #include <str ...

  6. python3安装docx模块出现Import Error: No module named 'exceptions'

    x首先 pip3 install docx 显示已经安装,但是 No module named 'exceptions' 网上查的资料命令行下载的docx安装包还没有完全兼容python3,第三方库应 ...

  7. wifi rate vs mode

  8. scrapy框架学习第一天

    今天是学习的第一天: 知识总结如下: 1,调试器相当于原料出口地(URL提供) 2,scrapy相当于中间加工商(具有销售权利)封装URL为request(请求) 3,下载器使用request(请求) ...

  9. 软件151 王楚博 maven的导入

    一.maven 包的导入 清单如下: <!-- Inherit defaults from Spring Boot --> <parent> <groupId>or ...

  10. 用git提交源代码

    码云账号 markliuning      作业已经上传 题目要求:定义一个包含有10个整数的数组a并初始化,定义一个指针变量p,p指向数组a,定义函数fun,在fun内部访问数组,并打印出数组中各元 ...