使用C++中string实现任意长度的正小数、整数之间加减法方法实例

一、概述

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 0;
   }
  }
 }
 for(auto c:num2)
 {
  if(!isdigit(c)||num2.empty())
  {
   if(c=='.'&&!num2Flag)
   {
    num2Flag=true;
   }
   else
   {
    cout<<"num2: Please input correct form!!!"<<endl;
    return 0;
   }
  }
 }

 //字符串分割{整数部分和小数部分)
 if(num1Flag)//如果是小数
 {
  int i=0;
  while(i!=num1.size()&&num1[i]!='.')
  {
   num11+=num1[i];
   ++i;
  }
  while(++i!=num1.size())
  {
   num12+=num1[i];
  }
  //用于.XXX或XXX.型输入的控制
  if(num11.empty())
   num11+='0';
  if(num12.empty())
   num12+='0';
 }
 else//如果是整数
 {
  num11=num1;
  num12+='0';
 }
 if(num2Flag)//如果是小数
 {
  int i=0;
  while(i!=num2.size()&&num2[i]!='.')
  {
   num21+=num2[i];
   ++i;
  }
  while(++i!=num2.size())
  {
   num22+=num2[i];
  }
  //用于.XXX或XXX.型输入的控制
  if(num21.empty())
   num21+='0';
  if(num22.empty())
   num22+='0';
 }
 else//如果是整数str
 {
  num21=num2;
  num22+='0';
 }

 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+='0';
 //反转字符串
 reverse(strLong2.begin(),strLong2.end());
 reverse(strShort2.begin(),strShort2.end());
 //小数部分进行加法计算
 string strRes2(strLong2.size(),'0');
 int carry=0;//进位
 for(int i=0; i!=strLong2.size(); ++i)
 {
  int a=strShort2[i]-'0',b=strLong2[i]-'0';
  a=a+b+carry;
  carry=a/10;
  strRes2[i]=(a%10)+'0';
 }
 //反转回来
 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(),'0');
 for(int i=0; i!=strShort1.size(); ++i)
 {
  int a=strShort1[i]-'0',b=strLong1[i]-'0';
  a=a+b+carry;
  carry=a/10;
  strRes1[i]=(a%10)+'0';
 }
 for(int i=strShort1.size(); i!=strLong1.size(); ++i)
 {
  int b=strLong1[i]-'0';
  b+=carry;
  carry=b/10;
  strRes1[i]=b%10+'0';
 }
 if(carry)
 {
  strRes1+=(carry+'0');
 }
 //反转回来
 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<=0)
 {
  for(int i=cntTemp;i!=0;++i)
  {
   strBjs2+='0';
  }
 }
 else
 {
  for(int i=cntTemp;i!=0;--i)
  {
   strJs2+='0';
  }
 }

 //反转字符串
 reverse(strBjs2.begin(),strBjs2.end());
 reverse(strJs2.begin(),strJs2.end());
 string strRes2(strBjs2.size(),'0');
 int carry=0;//进位
 for(int i=0; i!=strBjs2.size(); ++i)
 {
  int a=strBjs2[i]-'0',b=strJs2[i]-'0';
  a=a-b-carry;
  if(a>=0)
  {
   carry=0;
   strRes2[i]=a+'0';
  }
  else
  {
   carry=1;
   strRes2[i]=a+10+'0';
  }
 }
 //反转回来
 reverse(strRes2.begin(),strRes2.end());

 //整数部分进行减法计算
 //反转字符串
 reverse(strBjs1.begin(),strBjs1.end());
 reverse(strJs1.begin(),strJs1.end());
 string strRes1(strBjs1.size(),'0');
 for(int i=0;i!=strJs1.size();++i)
 {
  int a=strBjs1[i]-'0',b=strJs1[i]-'0';
  a=a-b-carry;
  if(a>=0)
  {
   carry=0;
   strRes1[i]=a+'0';
  }
  else
  {
   carry=1;
   strRes1[i]=a+10+'0';
  }
 }
 for(int i=strJs1.size();i!=strBjs1.size();++i)
 {
  int a=strBjs1[i]-'0';
  a=a-carry;
  if(a>=0)
  {
   carry=0;
   strRes1[i]=a+'0';
  }
  else
  {
   carry=1;
   strRes1[i]=a+10+'0';
  }
 }
 if(carry)//此时除数比被除数大,结果为负数
 {
  return "*";
 }
 //反转回来
 reverse(strRes1.begin(),strRes1.end());

 //清楚冗余0
 string strTemp;
 cntTemp=0;
 for(int i=0;strRes1[i]=='0';++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:对输出格式统一控制为小数类型

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • C++ string 字符串查找匹配实例代码

    在写C++程序中,总会遇到要从一个字符串中查找一小段子字符串的情况,对于在C中,我们经常用到strstr()或者strchr()这两种方法.而对于C++的string,我们往往会用到find(). C++:#inlcude<string> C: #include<string.h> find():在一个字符串中查找一个指定的单个字符或字符数组.如果找到,就返回首次匹配的开始位置:如果没有查找到匹配的内容,就返回string::npos. find_first_of():在一个目标串

  • 使用C++的string实现高精度加法运算的实例代码

    对于超大数字的运算,用long long int仍然不能解决,这时候就需要考虑通过模拟运算和数组存储来实现高精度运算. 本文讨论借助C++的string来实现高精度的运算. 首先输入的量直接存储为string,设为s1和s2. 接下来设计一个反转函数,用于把整个字符串反转(为了方便后续计算). string reverseStr(string input){ string output = ""; for(int i = 0; i < input.length(); i++){

  • C++中stringstream的用法和实例

    之前在leetcode中进行string和int的转化时使用过istringstream,现在大致总结一下用法和测试用例. 介绍:C++引入了ostringstream.istringstream.stringstream这三个类,要使用他们创建对象就必须包含sstream.h头文件. istringstream类用于执行C++风格的串流的输入操作. ostringstream类用于执行C风格的串流的输出操作. stringstream类同时可以支持C风格的串流的输入输出操作. 下图详细描述了几

  • 详解C++中String类模拟实现以及深拷贝浅拷贝

    详解C++中String类模拟实现以及深拷贝浅拷贝 在C语言中/C++中,字符串是一个应用很广泛的类型,也是很基础的类型,C语言并没有直接处理字符串的操作而是采用字符指针和字符串数组进行操作,而在C++中标准库为我们封装了一个字符串的类供我们使用,使用需要#inlcude <string>头文件.我们也可以自己模拟实现一个简单的String类. 在模拟实现String类的过程中,不可避免的会遇到深拷贝浅拷贝的问题,下面就深拷贝浅拷贝做一个简介.所谓深拷贝浅拷贝,简单来说就是浅拷贝只是简单的将值

  • C++中string的模拟实现

    c++中的string类可以实现字符串对象的一系列操作,如下图就是从cplusplus上截取的string的一部分功能: 接下来我就简单模拟几个函数实现 首先,我们要给出完整的string类,包括构造函数,析构函数,私有成员char* str 并且在类内声明要实现的函数(本文我只实现了operator=,operator[ ],pushback(),以及三个operator+=,五个insert等) #include<iostream> #include<cstring> usin

  • C++中将string类型转化为int类型

    写程序需要将string转化为int,所以就探索了一下. 方法一:atoi函数 atoi函数将字符串转化为整数,注意需要stdlib库.所以就尝试了一下: #include <iostream> #include <string.h> #include <stdlib.h> using namespace std; int main() { string a="11",b="22"; cout<<atoi(a)+ato

  • 从string类的实现看C++类的四大函数(面试常见)

    朋友面试的一道面试题,分享给大家,面试官经常会问到的,实现string类的四大基本函数必掌握. 一个C++类一般至少有四大函数,即构造函数.拷贝构造函数.析构函数和赋值函数,一般系统都会默认.但是往往系统默认的并不是我们所期望的,为此我们就有必要自己创造他们.在创造之前必须了解他们的作用和意义,做到有的放矢才能写出有效的函数. #include <iostream> class CString { friend std::ostream & operator<<(std::

  • 使用C++中string实现任意长度的正小数、整数之间加减法方法实例

    一.概述 C/C++中的int类型能表示的范围是-2E31-2E31–1.unsigned类型能表示的范围是0-2E32–1,即 0-4294967295.所以,int和unsigned类型变量,都不能保存超过10位的整数.有时我们需要参与运算的数,可能会远远不止10 位,例如,可能需要保留小数点后面100位(比如求π的值),那么,即便使用能表示很大数值范围的double变量,但是由于double变量只有64位,所以还是不可能达到精确到小数点后面100位这样的精度.double变量的精度也不足以

  • Java任意长度byte数组转换为int数组的方法

    前言 嗯.最近工程上遇到一个byte数组转换为int的问题,解决过程中遇到了几个坑,经过各种查资料终于还是解决了.撒花. Java的位运算以及byte数组与其他类型数据的转换比c/c++感觉麻烦一些.这里简单说明一下byte数组和int的转换吧. 总所周知,int类型数据在Java中占据32 bit,byte占据8 bit,这样的话,正常情况下4个byte可以转换成一个int类型数据. 当然,不正常情况下,3个byte或者2个byte甚至1个byte都可以转换为int数据,只需要高位补上就行.

  • vuejs中父子组件之间通信方法实例详解

    本文实例讲述了vuejs中父子组件之间通信方法.分享给大家供大家参考,具体如下: 一.父组件向子组件传递消息 // Parent.vue <template> <div class="parent"> <v-child :msg="message"></v-child> </div> </template> <script> import VChild from './child.v

  • Java中String.format的使用方法总结

    Java中String.format的用法总结 1.对整数进行格式化:%[index$][标识][最小宽度]转换方式 我们可以看到,格式化字符串由4部分组成,其中%[index$]的含义我们上面已经讲过,[最小宽度]的含义也很好理解,就是最终该整数转化的字符串最少包含多少位数字.我们来看看剩下2个部分的含义吧: 标识: '-' 在最小宽度内左对齐,不可以与"用0填充"同时使用 '#' 只适用于8进制和16进制,8进制时在结果前面增加一个0,16进制时在结果前面增加0x '+' 结果总是

  • Python cookbook(数据结构与算法)从任意长度的可迭代对象中分解元素操作示例

    本文实例讲述了python从任意长度的可迭代对象中分解元素操作.分享给大家供大家参考,具体如下: 从某个可迭代对象中分解出N个元素,但是可迭代对象的长度可能超过N,会出现"分解值过多"的异常: 使用"*表达式"来解决该问题: Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (Intel)] on win32 Type "copyright",

  • java中String StringBuffer和StringBuilder的区别详解

    目录 从声明定义上来谈 从结构上来谈 从线程安全来谈 总结 从声明定义上来谈 只有String 可以 直接声明创建 而 StringBuffer 与 StringBuilder 必须去new对象 这是因为只有String会在这种声明方式下去字符串常量池创建,其他则没有 StringBuffer stf = new StringBuffer("abc"); StringBuilder stb = new StringBuilder("abc"); StringBuff

  • 一文搞懂Redis中String数据类型

    概述: 字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这便意味着该类型可以接受任何格式的数据,如JPEG图像数据或Json对象描述信息等.在Redis中字符串类型的Value最多可以容纳的数据长度是512M. 相关命令列表: 命令原型 时间复杂度 命令描述 返回值 APPEND O(1)  如果该Key已经存在,APPEND命令将参数Value的数据追加到已存在Value的末尾.如果该Key不存在,APPEND命令将会创建一个新的Key/Value. 追加后Va

  • Java中String的split切割字符串方法实例及扩展

    目录 一.public String[] split(String regex) 二.public String[] split(String regex, int limit) 三.扩展 总结 一.public String[] split(String regex) public String[] split(String regex): 根据传入的字符串参数,作为规则,切割当前字符串 String a="198,168,10,1"; String [] arr=a.split(&

  • Java中String类的常用方法总结

    目录 概述 特点 使用步骤 常用方法 判断功能的方法 获取功能的方法 转换功能的方法 分割功能的方法 概述 java.lang.String 类代表字符串.Java程序中所有的字符串文字(例如"abc" )都可以被看作是实现此类的实例. 类 String 中包括用于检查各个字符串的方法,比如用于比较字符串,搜索字符串,提取子字符串以及创建具有翻 译为大写或小写的所有字符的字符串的副本. 特点 字符串不变:字符串的值在创建后不能被更改. String s1 = "abc&quo

  • java中String的常见用法总结

    1>获取  1.1:字符串中包含的字符数,也就是字符串的长度.  int length():获取长度 1.2:根据位置获取位置上某个字符.  char charAt(int index) 1.3:根据字符获取该字符在字符串中的位置.  int indexOf(int ch):返回的是ch在字符串中第一次出现的位置.  int indexOf(int ch,int fromIndex):从fromIndex指定位置开始,获取ch在字符串中出现的位置. int indexOf(String str)

随机推荐