标签:计算器 大数运算实现加减乘除四则运算 大数运算 大数运算项目
首先,让我们先来熟悉一下两种防止头文件被重复引用的处理#pragma once和#ifndef的区别
http://10739786.blog.51cto.com/10729786/1730827
接下来,开始我们的主题 <大数运算>
在平时生活中细心的你可能会发现,好多时候我们使用计算器时,总有一个显示的最大值,当计算超过这个值时就不能再计算了,那如果我们想要计算更大的数值要怎么办?
本文通过C++编程实现 大数的加减乘除四则运算
<思路与方法同样都在程序内部>
这次通过标准的三个文件来实现声明<BIGDATA.h>、定义实现函数功能<BIGDATA.cpp>、测试<test.cpp>
<BIGDATA.h>
#pragma once #ifndef __BIGDATA_H__ #define __BIGDATA_H__ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> using namespace std; #include<string.h> #include<assert.h> //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<<endl;将不能通过 BigData Add(string pData1, string pData2);//并不一定要写成成员函数 (也可以写成一般函数被使用) BigData Sub(string pData1, string pData2); BigData Mul(string pData1, string pData2); BigData Div(string pData1, string pData2); private: INT64 _value; string _pData; }; #endif __BIGDATA_H__ //<BIGDATA.cpp> #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) 头文件<ctype.h> 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<<endl;将不能通过 { if (!bigdata.PDataIsOverINT64()) { _cout << bigdata._value; } else { char* tmp = (char*)&bigdata._pData[0]; if (‘+‘ == *tmp) { tmp++; } while (*tmp) { _cout << *tmp++; } //_cout << endl; } return _cout; } void BigData::Print() { if (!PDataIsOverINT64()) { cout << _value << endl; //printf("%lld\n", _value); return; } if (*(char*)&_pData[0] == ‘+‘) { printf("%s\n", &_pData[1]); return; } printf("%s\n",&_pData[0]); } void Invert(string& pdata) { int left = 1; int right = pdata.size() - 1; while (left < right) { swap(pdata[left++], pdata[right--]); } } BigData BigData:: operator+(const BigData bigdata) { //1、都在INT64范围内<运算后在范围内,运算后不在范围内>(再进行构造可以解决) //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; } //<test.cpp> #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; }
标签:计算器 大数运算实现加减乘除四则运算 大数运算 大数运算项目
原文地址:http://10739786.blog.51cto.com/10729786/1760845