首先,让我们先来熟悉一下两种防止头文件被重复引用的处理#pragma once和#ifndef的区别
http://10739786.blog.51cto.com/10729786/1730827
接下来,开始我们的主题 <大数运算>
在平时生活中细心的你可能会发现,好多时候我们使用计算器时,总有一个显示的最大值,当计算超过这个值时就不能再计算了,那如果我们想要计算更大的数值要怎么办?
本文通过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;
}