大数运算实现加减乘除四则运算

首先,让我们先来熟悉一下两种防止头文件被重复引用的处理#pragma once和#ifndef的区别


        http://10739786.blog.51cto.com/10729786/1730827


    接下来,开始我们的主题 <大数运算>
    在平时生活中细心的你可能会发现,好多时候我们使用计算器时,总有一个显示的最大值,当计算超过这个值时就不能再计算了,那如果我们想要计算更大的数值要怎么办?

650) this.width=650;" title="QQ截图20160406133205.jpg" src="http://s5.51cto.com/wyfs02/M00/7E/92/wKiom1cEn5SCORz_AADVcMQzbig698.jpg" alt="wKiom1cEn5SCORz_AADVcMQzbig698.jpg" />


    本文通过C++编程实现 大数的加减乘除四则运算


    <思路与方法同样都在程序内部>

    这次通过标准的三个文件来实现声明、定义实现函数功能、测试


#pragma once

#ifndef __BIGDATA_H__
#define __BIGDATA_H__

#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;
#include
#include

//1、考虑当数值小时,运算速度尽量贴近内置类型(所以,结构会有两个-->内置类型long long 及大数的 char*)
//2、构造时可能的输入{"1234" "0001234"  "1564adf"  "   "  "+(-)12345" }
//

typedef long long INT64;

//string MAX_INT64 = "9223372036854775807";
//string MIN_INT64 = "-9223372036854775808";

//enum{ MAX_INT64 = 9223372036854775807, MIN_INT64 = -9223372036854775808 };//不行enum后是int类型
//

const INT64 MAX_INT64 = 0x7fffffffffffffff;// 9223372036854775807;
const INT64 MIN_INT64 = 0x8000000000000000;//-9223372036854775808;


class BigData
{
public:
 BigData(INT64 value = 0);
 BigData(const string pData);

 BigData operator+(const BigData bigdata);
 BigData operator-(const BigData bigdata);
 BigData operator*(const BigData bigdata);
 BigData operator/(const BigData bigdata);

 ~BigData();

 void Print();

private:
 bool PDataIsOverINT64()const;
 friend std::ostream&operator<<(std::ostream& _cout, const BigData& bigdata);//不能在_cout前加const   ->_cout<<10<


#include"BIGDATA.h"

BigData::BigData(INT64 value)//若输入的数值位数大于MAX_DATA,系统编译不通过,当位数一致且大于时,转为负,无能为力
 :_value(value)
{
 //在_pData中加入value
 void Invert(string& pdata);
 size_t i = 0;
 INT64 tmp = 0;
 _pData.append(1, '+');
 if (value < 0)
 {
  _pData[0] = '-';
  value *= -1;
 }
 while (value != 0)
 {
  tmp = value % 10;
  _pData.append(1, (char)(tmp + '0'));
  value /= 10;
 }
 Invert(_pData);
}

BigData::BigData(const string  pData)
{
 //解决各种特殊情况
 //{"1234" "0001234"  "1564adf"  "   "  "+(-)12345" NULL }
 //参考atoi()函数处理办法
 

 //跳过符号将输入字符串都归为一般

//  //判是否是数字字符isdigit(int c)是-1/否0  还有判空字符(宏定义) isspace(int c)  头文件

 char* tmp = (char*)&pData[0];
 _pData.append(1, '+');  //添加符号(默认为'+')

 if ((*tmp < '0' || *tmp > '9') && *tmp != ' '&& *tmp != '+'&& *tmp != '-'&& *tmp != '\t')  //排除其他符号
 {
  //cout << "false" << endl;
  _pData.append(1, '0');
  _value = 0;
  return;
 }

 while(isspace(*tmp)) //while (*tmp==' ')   //消除前面的空格(tab)
 {
  tmp++;
 }

 if (*tmp == '+' || *tmp == '-')  //跳过符号/修正符号
 {
  if (*tmp == '-')
  {
   _pData[0] = '-';
  }
  tmp++;
 }

 while (*tmp == '0')   //消除前面的0(必须先消除空格,再消除0,最后判断+(-))
 {
  tmp++;
 }

//*********************
 //一个一个追加效率不高-->转化为一次开辟
 //while(isdigit(*tmp))  //while (*tmp >= '0'&& *tmp <= '9')
 //{
 // _pData.append(1, *tmp++);
 //}
//*********************

 _pData.resize(strlen(tmp) + 1);
 int i = 1;
 while (isdigit(*tmp))
 {
  _pData[i++] = *tmp++;
 }

 if (*tmp != '\0')
 {
  //cout << "false" << endl;
  _value = 0;
  return;
 }

 //若超出INT64表示的范围则用string管理,否则用INT64,string综合管理
 if (!PDataIsOverINT64())
 {
  size_t i = 1;
  _value = 0;
  for (i = 1; i < _pData.size(); i++)
  {
   _value = _value * 10 + _pData[i] - '0';
  }
  if (_pData[0] == '-')
   _value *= -1;
 }

}

BigData::~BigData()
{}

bool BigData::PDataIsOverINT64()const
{
 std::string tmp("+9223372036854775807");
 if (_pData[0] == '-')
 {
  tmp = "-9223372036854775808";
 }

 if ((_pData.size() < tmp.size())||
  (_pData.size() == tmp.size() && _pData <= tmp))
 {
  return false;
 }
 return true;

}

std::ostream& operator<<(std::ostream& _cout, const BigData& bigdata)//不能在_cout前加const   ->_cout<<10<(再进行构造可以解决)
 //2、都不在INT64范围内<运算后在范围内,运算后不在范围内>
 //3、一个在一个不在<运算后在范围内,运算后不在范围内>
 //
 //如果全部用string进行计算,就达不到数值小时用基本类型提高运算的目的
 //由于实现结构是若在INT64范围内_value与_pData共同管理,若不在只由_pData管理

 //所以,可以将上面分化成两类<1、都在范围内(<运算后在范围内,运算后不在范围内>) 2、至少有一个不在范围内>


 if (!PDataIsOverINT64() && !bigdata.PDataIsOverINT64())
 {
  if (_pData[0] != bigdata._pData[0])//若异号,则肯定不会溢出
  {
   return BigData(_value + bigdata._value);
  }
  else //同号
  {
   if (_pData[0] == '+')//为正
   {
    if (_value <= MAX_INT64 - bigdata._value)//结果不溢出
    {
     return BigData(_value + bigdata._value);
    }
    else //结果溢出
    {
     return BigData(Add(_pData, bigdata._pData));
    }
   }
   else //为负
   {
    if (_value >= MIN_INT64 - bigdata._value)//结果不溢出
    {
     return BigData(_value + bigdata._value);
    }
    else //结果溢出
    {
     return BigData(Add(_pData, bigdata._pData));
    }
   }
  }
 }
 else//至少有一个溢出
 {
  return BigData(Add(_pData, bigdata._pData));
 }
}



BigData BigData:: operator-(const BigData bigdata)
{
 //1、都在范围内(运算后在范围内,运算后不在范围内) 
 //2、至少有一个不在范围内

 if (!PDataIsOverINT64() && !bigdata.PDataIsOverINT64())
 {
  //同号相减不可能溢出,异号相减才可能溢出

  if (_pData[0] == bigdata._pData[0])//同号
  {
   return BigData(_value - bigdata._value);
  }
  else// 异号
  {
   if (_pData[0] == '+')//第一个为正,第二个为负
   {
    if (_value < MAX_INT64 + bigdata._value)//结果不溢出
    {
     return BigData(_value - bigdata._value);
    }
    else   //结果溢出
    {
     return Sub(_pData, bigdata._pData);
    }
   }
   else //第一个为负,第二个为正
   {
    if (_value > MIN_INT64 + bigdata._value)//结果不溢出
    {
     return BigData(_value - bigdata._value);
    }
    else   //结果溢出
    {
     return Sub(_pData, bigdata._pData);
    }
   }
  }
 }
 else
 {
  return Sub(_pData, bigdata._pData);
 }
}

void _EachAdd0(string& pdate) //各项添加'0'
{
 int size = pdate.size();
 int i = 1;
 for (i = 1; i < size; i++)
 {
  pdate[i] += '0';
 }
}

void _EachSub0(string& pdate) //各项去'0'
{
 int size = pdate.size();
 int i = 1;
 for (i = 1; i < size; i++)
 {
  pdate[i] -= '0';
 }
}

BigData BigData:: Add(string pData1, string pData2)
{
 //转化为string中从低到高字符相加
 //若同号 就相加,若异号,转为减

 if (pData1[0] != pData2[0])//异号
 {
  if (pData1[0] == '+')
  {
   pData2[0] = '+';
   return Sub(pData1, pData2);
  }
  else
  {
   pData1[0] = '+';
   return Sub(pData2, pData1);
  }
 }
 else//同号  
 {
  //判断哪个位数多,放在前面
  if (pData1.size() < pData2.size())
  {
   swap(pData1, pData2);
  }

  std::string tmp;
  int size1 = pData1.size();
  int size2 = pData2.size();
  int sizet = size1 + 1;
  int flag = 0;
  tmp.resize(size1 + 1);
  tmp[0] = pData1[0];

  for (int i = 0; i < size1 - 1; i++)
  {
   flag = 0;
   char cur = '0';
   if (size2 - 1 - i > 0)
   {
    cur = pData2[size2 - 1 - i];
   }
   tmp[sizet - i-1] = pData1[size1 - 1 - i] + cur - 2 * '0';//tmp存数值而不是数字字符
   if (tmp[size1 - i] / 10 == 1)
   {
    flag = 1;
    tmp[size1 - i] %= 10;
   }
   
   pData1[size1 - i - 2] += flag;
  }
  tmp[1] = flag;
  _EachAdd0(tmp);

  return BigData(tmp);
 }
}


BigData BigData::Sub(string pData1, string pData2)
{
 //转化为string中从低到高字符相减
 //若同号 就相减(注意前后位数不同),若异号,转为加

 if (pData1[0] != pData2[0])//异号
 {
  if (pData1[0] == '+')
  {
   pData2[0] = '+';
   return Add(pData1, pData2);
  }
  else
  {
   pData2[0] = '-';
   return Add(pData1, pData2);
  }
 }
 else  //同号
 {
  //取数值的符号,将较大值放在前面

  if (pData1.size() < pData2.size() ||
   (pData1.size() == pData2.size() && (strcmp(pData1.c_str(), pData2.c_str()) < 0)))
  {
   if (pData1[0] == '+')
   {
    pData2[0] = '-';
   }
   else
   {
    pData2[0] = '+';
   }
   swap(pData1, pData2);   
  }
  std::string tmp;
  int size1 = pData1.size();
  int size2 = pData2.size();
  int sizet = size1;
  int flag = 0;
  tmp.resize(sizet);
  tmp[0] = pData1[0];
  for (int i = 0; i < size1 - 1; i++)
  {
   flag = 0;
   int cur = 0;
   if (i < size2 - 1)
   {
    cur = pData1[size1 - i - 1] - pData2[size2 - i - 1];
   }
   else
   {
    cur = pData1[size1 - i - 1] - '0';
   }
   if (cur < 0)
   {
    flag = 1;
    cur += 10;
   }
   tmp[sizet - 1 - i] = cur + '0';

   pData1[size1 - 2 - i] -= flag;

  }
  return BigData(tmp);
 }
}


BigData BigData:: operator*(const BigData bigdata)
{
 //1、都在INT64范围内<运算后在范围内,运算后不在范围内>
 //   同号与 MAX_DATA比较  异号与MIN_DATA比较
 //2、至少一个不在范围内
 if (0 == _value || 0 == bigdata._value)
 {
  return BigData(0);
 }
 if (!PDataIsOverINT64() && !bigdata.PDataIsOverINT64())
 {
  if (_pData[0]==bigdata._pData[0])//同号
  {
   if (_value >= 0)//为正
   {
    if (_value < MAX_INT64 / bigdata._value)//结果在范围内
    {
     return BigData(_value*bigdata._value);
    }
    else // 结果不在范围内
    {
     return Mul(_pData,bigdata._pData);
    }
   }
   else//为负
   {
    if (_value > MAX_INT64 / bigdata._value)//结果在范围内
    {
     return BigData(_value*bigdata._value);
    }
    else // 结果不在范围内
    {
     return Mul(_pData, bigdata._pData);
    }
   }
  }
  else  //异号
  {
   if (_value >= 0)//为正 负
   {
    if (_value < MIN_INT64 / bigdata._value)//结果在范围内
    {
     return BigData(_value*bigdata._value);
    }
    else // 结果不在范围内
    {
     return Mul(_pData, bigdata._pData);
    }
   }
   else //为 负 正
   {
    if (_value > MIN_INT64 / bigdata._value)//结果在范围内
    {
     return BigData(_value*bigdata._value);
    }
    else // 结果不在范围内
    {
     return Mul(_pData, bigdata._pData);
    }
   }
  }
 }
 else
 {
  return Mul(_pData, bigdata._pData);
 }
}

BigData BigData::Mul(string pData1, string pData2)
{
 //同号 异号  先大数 后小数  
 //为提高效率 外层循环次数少,内层次数多

 std::string tmp;
 int size1 = pData1.size();
 int size2 = pData2.size();
 int sizet = size1 + size2;
 tmp.resize(size1 + size2);
 tmp[0] = '+';
 if (pData1[0] != pData2[0])//同号 异号 
 {
  tmp[0] = '-';
 }

 if (size1 < size2 || (size1 == size2&&strcmp(&pData1[0], pData2.c_str()) < 0))//先大数 后小数
 {
  swap(pData1, pData2);
  swap(size1, size2);
 }

 _EachSub0(pData1);
 _EachSub0(pData2);
 //tmp初始化时 全为 0
 for (int i = 1; i < size2; i++)//小数位数  
 {
  if (pData2[size2 - i] == 0)  //若位数上为0则跳过
  {
   continue;
  }
  for (int j = 1; j < size1; j++)//大数位数
  {
   if (pData1[size1 - j] == 0)  //若位数上为0则跳过
   {
    continue;
   }
   tmp[sizet - j - i + 1] += pData1[size1 - j] * pData2[size2 - i];
   if (tmp[sizet - j - i + 1]>=10)
   {
    tmp[sizet - j - i] += tmp[sizet - j - i + 1] / 10;
    tmp[sizet - j - i + 1] %= 10;
   }
  }

 }

 for (int i = 0; i < sizet - 1; i++)
 {
  if (tmp[sizet - i - 1] >= 10)
  {
   tmp[sizet - i - 2] += tmp[sizet - i - 1] / 10;
   tmp[sizet - i - 1] %= 10;
  }
 }

 _EachAdd0(tmp);
 return BigData(tmp);
}

BigData BigData:: operator/(const BigData bigdata)
{
 //1、排除除数为0
 //2、在范围内,不在范围内
 //3、不在范围内<左(被除数)比右(除数)小为0,左比右大>
 //4、正负

 if (0 == bigdata._value)
 {
  assert(false);
 }

 if (!PDataIsOverINT64() && !bigdata.PDataIsOverINT64())
 {
  return BigData(_value / bigdata._value);
 }
 else
 {
  //左(被除数)比右(除数)小为0
  if (_pData.size() < bigdata._pData.size() ||
   (_pData.size() == bigdata._pData.size() && _pData[0] == bigdata._pData[0]&&
   strcmp((char*)&_pData[0],(char*)&bigdata._pData[0]) < 0))
  {
   return BigData(0);//正0 负0 都记为0 
  }
  else //左比右大
  {
   return Div(_pData, bigdata._pData);
  }
 }
}



BigData BigData::Div(string pData1, string pData2)
{
 //正负且 参数左大右小
 char* _trueDiv(char* tp1, char* tmp2, int size, string& cur);

 string cur;
 cur.append(1, '+');
 if (pData1[0] != pData2[0])
 {
  cur[0] = '-';
 }

 char* tmp1 = (char*)malloc(pData1.size());// *tmp2 = (char*)malloc(pData2.size());
 strcpy(tmp1, &pData1[1]); //strcpy内部实现free(tmp1)
 char*tmp2 = &pData2[1];
 int size2 = strlen(tmp2);
 int sizermd = size2;
 int excursion = size2;
 char* rmd = NULL;

 while (strlen(tmp1) > strlen(tmp2) || 
  (strlen(tmp1) == strlen(tmp2) && strcmp(tmp1, tmp2) > 0))//左大于右时,循环
 {  
  while (sizermd < size2 || (sizermd == size2&&strncmp(tmp1, tmp2, sizermd)<0))//不够 商0
  {
   cur.append(1, '0');
   sizermd++;
   ++excursion;
  }

  rmd = _trueDiv(tmp1, tmp2, sizermd, cur);// 16713  31071  
  sizermd = strlen(rmd);
  
  strcat(rmd, &pData1[++excursion]);

  tmp1 = rmd;
  sizermd++;  // 将余数与剩余被除数相接
 }

 return BigData(cur);
}

char* _trueDiv(char* tp1, char* tp2, int size1, string& cur)
{
 //只有tp1和 tp2位数相同且比tp2大,或者比tp2多一位的情况
 int size2 = strlen(tp2);

 int i = 0;
 tp1[size1] = '\0';

 char count = 0;
 int flag = 0;

 while (size1 > size2 ||
  (size1 == size2&&strcmp(tp1, tp2) > 0))//tp1大于tp2
 {
  for (i = 0; i < size1; i++)
  {
   flag = 0;
   int count = 0;
   if (i < size2)
   {
    count = tp1[size1 - i - 1] - tp2[size2 - i - 1];
   }
   else
   {
    count = tp1[size1 - i - 1] - '0';
   }
   if (count < 0)
   {
    flag = 1;
    count += 10;
   }
   tp1[size1 - 1 - i] = count + '0';

   tp1[size1 - 2 - i] -= flag;

   while (*tp1 == '0' && size1>1)//可能出现整除情况
   {
    tp1++;
    size1--;
   }

  }
  count++;
 }

 cur.append(1, count + '0');
 return tp1;
}


//


#include"BIGDATA.h"

void test()
{
 BigData b0(13215156);
 BigData b10(-13215156);
 BigData b11(9787687678661325156);//当传入的数值大于MAX_DATA且位数相等时,编译器不能检测,导致由正转负
 BigData b12(-9223372036854775807);
 BigData b1("a13215jfiow");
 b1.Print();
 cout << b1<< endl;
 BigData b2("+000023215");
 cout << b2 << endl;
 b2.Print();
 BigData b3(" 33215jfiow"); //(Tab、空格键消除用isspace(int))
 cout << b3 << endl;
 b3.Print();
 BigData b4("    -33215jfiow");
 cout << b4 << endl;
 b4.Print();
 BigData b5("43215jfiow");
 b5.Print();
 cout << b5 << endl;

 //BigData b6("4321537537354373783783");
 //b6.Print(); 
 //cout << b6 << endl;
 BigData b7("-43215378338735373783537");
 cout << b7 << endl;
 b7.Print();
 BigData b8("-9223372036854775808");
 cout << b8 << endl;
 b8.Print();
 BigData b9("-999999");
 cout << b9 << endl;
 b9.Print();

 BigData b101("43215378338735373783537");
 BigData b102("-43215378338735373783537");
 BigData b103("-43215378338735373783537");
 BigData b110("-43215378338735373783537");

 (b2 + b9).Print();
 cout << (b2 + b9) << endl;
}

void testAdd()
{
 BigData b1("-45353");
 BigData b2("37353753");
 BigData b3("-9223372036854775808");
 BigData b4(" 9223372036854775800");
 BigData b5("-9223372036854775810");
 BigData b6(" 9223372036854775900");

 cout << (b1 + b1) << endl; 
 cout << (b2 + b2) << endl;
 cout << (b1 + b2) << endl;
 cout << (b1 + b4) << endl;

 cout << b3 << endl;
 cout << (b1 + b3) << endl;
 cout << (b2 + b4) << endl;

 cout << (b2 + b5) << endl;
 cout << (b1 + b6) << endl;
 cout << (b6 + b1) << endl;

}

void testSub()
{
 BigData b1("-45353");
 BigData b2("37353753");
 BigData b3("-9223372036854775808");
 BigData b4(" 9223372036854775800");
 BigData b5("-9223372036854775810");
 BigData b6(" 9223372036854775900");

 cout << (b1 - b2) << endl;
 cout << (b2 - b1) << endl; 
 cout << (b3 - b1) << endl;
 cout << (b1 - b4) << endl;
 cout << (b3 - b2) << endl;
 cout << (b4 - b1) << endl;
 cout << (b1 - b3) << endl;
 cout << (b2 - b4) << endl;
 cout << endl;


 cout << (b5 - b1) << endl;
 cout << (b1 - b5) << endl;
 cout << endl;
 cout << (b6 - b2) << endl;
 cout << (b2 - b6) << endl;
 cout << endl;
 cout << (b6 - b5) << endl;
 cout << (b5 - b6) << endl;
 cout << (b2 - b5) << endl;
 cout << (b1 - b6) << endl;
 cout << (b6 - b1) << endl;

}


void testMul()
{
 BigData b1("-45353");
 BigData b2("37353753");
 BigData b3("-9223372036854775808");
 BigData b4(" 9223372036854775800");
 BigData b5("-9223372036854775810");
 BigData b6(" 9223372036854775900");

 cout << (BigData("999") * BigData("22222222222222222222222222222")) << endl;

 cout << (b2 * b1) << endl;
 cout << (b1 * b2) << endl;
 cout << (b1 * BigData(0)) << endl;
 cout << (BigData(0) * b2) << endl;
 cout << endl;
 cout << (b3 * b1) << endl;
 cout << (b1 * b3) << endl;
 cout << (b1 * b4) << endl;
 cout << (b4 * b1) << endl;
 cout << (b3 * b2) << endl;
 cout << (b2 * b4) << endl;
 cout << endl;


 cout << (BigData(0) * b6) << endl;
 cout << (b5 * BigData(0)) << endl;
 cout << (b5 * b1) << endl;
 cout << (b1* b5) << endl;
 cout << endl;
 cout << (b6 * b2) << endl;
 cout << (b2 * b6) << endl;
 cout << endl;
 cout << (b6 * b5) << endl;
 cout << (b5 * b6) << endl;
 cout << (b2 * b5) << endl;
 cout << endl;
 cout << (b1 * b6) << endl;
 cout << (b6 * b1) << endl;
 BigData b7("-203367738338252");
 cout << b7*b1 << endl;
}


void testDiv()
{
 BigData b1("-45353");
 BigData b2("37353753");
 BigData b3("-9223372036854775808");
 BigData b4(" 9223372036854775800");
 BigData b5("-9223372036854775810");
 BigData b6(" 9223372036854775900");
 BigData b7("-1231123203367738338252");


 //1、排除除数为0
 //cout << (b1 / BigData(0)) << endl;

 //2、在范围内

 cout << (b1 / b2) << endl;
 cout << (b2 / b1) << endl;


 //3、不在范围内<左(被除数)比右(除数)小为0,左比右大>
 cout << (b2 / b5) << endl;
 cout << (b2 / b6) << endl;

 cout << (b5 / b2) << endl;
 cout << (b6 / b2) << endl;
 cout << (b6 / b1) << endl;
 cout << (b5 / b1) << endl;

 cout << b7 / b1 << endl;
}

int main()
{
 //testAdd();
 //testSub();
 //testMul();
 testDiv();
 system("pause");
 return 0;
}


你可能感兴趣的:(大数运算实现加减乘除四则运算)