大数项目:用字符串表示超过内存表示范围的大数据并实现四则运算
2016-07-15 22:44
585 查看
原理很简单,直接上代码。
这里是初级版,效率低下,代码复杂不明了。只是尽可能的实现功能,改进版将在后续推出。
这里是头文件 BigData.h
BigData.cpp
最后是一组简单的测试函数
代码逻辑都很简单,只是写起来比较费事,所以如此冗长。
这里是初级版,效率低下,代码复杂不明了。只是尽可能的实现功能,改进版将在后续推出。
这里是头文件 BigData.h
#pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<assert.h> typedef long long INT_64; #define MAX_INT_64 0x7fffffffffffffff #define MIN_INT_64 -9223372036854775807 INT_64 Stoll(const std::string &s1); std::string onlynum(const std::string &str); void MulAdd(std::string& tmp, int RIdx); class BigData { public: BigData(INT_64 value = 0); BigData(std::string &str); BigData(const char* a); friend std::ostream& operator<<(std::ostream&os, const BigData&bigdata); BigData& operator=(const BigData&bigdata); bool _IsINT64Overflow()const; BigData operator+(const BigData&bigdata); BigData operator-(const BigData&bigdata); BigData operator*(const BigData&bigdata); BigData operator/(const BigData&bigdata); int DivSub(std::string& tmp, std::string& pRight); bool IsLessThanDiv(std::string& pRight, std::string& tmp); private: std::string Add(std::string left, std::string right); std::string Sub(std::string left, std::string right); std::string Mul(std::string left, std::string right); std::string Div(std::string left, std::string right); private: INT_64 _value; std::string _strData; };
BigData.cpp
#include"BigData.h" using namespace std; BigData::BigData(INT_64 value) :_value(value) { int count = 0; INT_64 tmp = _value; while (tmp) { count++; tmp /= 10; } int size = count + 1; _strData.resize(size); if (_value >= 0) { _strData[0] = '+'; tmp = _value; } else { _strData[0] = '-'; tmp = -_value; } char cRet = 0; while (tmp) { cRet = tmp % 10 + '0'; tmp /= 10; _strData[count--] = cRet; } } bool BigData::_IsINT64Overflow() const { if (_strData.size()<20) { return false; } if (_strData.size() == 20) { char* str="9223372036854775807"; int ret=_strData.compare(1, 19, str); if (ret <= 0) { return false; } } return true; } BigData::BigData(std::string &str) :_value(0) { str=onlynum(str); if ((str[0] != '-') && (str[0] != '+')) { _strData = "+"; _strData = _strData + str; } else { _strData = _strData + str; } if (!_IsINT64Overflow()) { _value = Stoll(_strData); } } BigData::BigData(const char* a) { assert(a); char cSymbol = a[0]; if (a[0] <= '9'&&a[0] >= '0') { cSymbol = '+'; } else if (a[0] == '+' || a[0] == '-') { a++; } else { _value = 0; return; } while (*a == '0') { a++; } _strData.resize(strlen(a) + 1); _strData[0] = cSymbol; int iCount = 1; _value = 0; while (*a >= '0'&& *a <= '9') { _strData[iCount++] = *a; _value = _value * 10 + *a - '0'; a++; } if (cSymbol == '-') { _value = 0 - _value; } _strData.resize(iCount); } ostream& operator<<(ostream&os, const BigData&bigdata) { if (bigdata._strData == "") { os << bigdata._value; } if (!bigdata._IsINT64Overflow()) { os << bigdata._value; } else { char* pData = (char*)bigdata._strData.c_str();// os << pData; } return os; } BigData& BigData::operator=(const BigData&bigdata) { _value = bigdata._value; _strData = bigdata._strData; return *this; } INT_64 Stoll(const string &s1) { char cSymbol = s1[0]; int icount = 0; if (cSymbol >= '0' && cSymbol <= '9') { cSymbol = '+'; } else if ('+' == cSymbol || '-' == cSymbol) { ++icount; } else { return 0; } while ('0' == s1[icount]) { ++icount; } INT_64 _ret = 0; while (s1[icount] >= '0' && s1[icount] <= '9') { _ret = _ret * 10 + (s1[icount]) - '0'; icount++; } if ('-' == cSymbol) { _ret = 0 - _ret; } return _ret; } string onlynum(const string &str) { string ret=str; if (ret == "") { ret = "+0"; return ret; } int iCount = 0; int idx = 0; while (' ' == ret[idx]) { ++idx; } char cSymbol = ret[idx]; if ('+' == cSymbol || '-' == cSymbol) { iCount++; } else { if (cSymbol > '0' || cSymbol <= '9') { cSymbol = '+'; } } while ('0' == ret[iCount + idx]) { ++idx; } while (ret[iCount + idx] >= '0' && ret[iCount + idx] <= '9') { ++iCount; } ret.erase(1, idx); ret.resize(iCount); return ret; } BigData BigData::operator+(const BigData& bigData) { if (!_IsINT64Overflow() && !bigData._IsINT64Overflow()) { if (_strData[0] != bigData._strData[0]) { return BigData(_value + bigData._value); } else { if (('+' == _strData[0] && MAX_INT_64 - _value >= bigData._value) || ('-' == _strData[0] && MIN_INT_64 - _value <= bigData._value)) { return BigData(_value + bigData._value); } } } //超出 if (_strData[0] == bigData._strData[0]) { return BigData(Add(_strData, bigData._strData)); } return BigData(Sub(_strData, bigData._strData)); } std::string BigData::Add(std::string left, std::string right) { int Lsize = left.size(); int Rsize = right.size(); if (Lsize < Rsize) { swap(left, right); swap(Lsize, Rsize); } string strRet; strRet.resize(Lsize + 1, '0'); strRet[0] = left[0]; //逐位相加 int cstep = 0; for (int iIdx = 1; iIdx < Lsize; iIdx++) { int cRet = left[Lsize - iIdx] - '0' + cstep; if (iIdx < Rsize) { cRet += right[Rsize - iIdx] - '0'; } strRet[Lsize - iIdx + 1] = cRet % 10 + '0'; cstep = cRet / 10; } strRet[1] = cstep + '0'; return strRet; } string BigData::Sub(std::string left, std::string right) { char* pleft = (char *)left.c_str(); char* pright = (char *)right.c_str(); int Lsize = left.size(); int Rsize = right.size(); string strRet; strRet.resize(Lsize); if (Lsize == Rsize) { if ((strcmp(pleft+1, pright+1) >= 0 && left[0] == '+') || (strcmp(pleft+1, pright+1) < 0 && left[0] == '-')) { strRet[0] = '+'; } else { strRet[0] = '-'; } } if (Lsize < Rsize) { if (left[0] == '-') { strRet[0] = '+'; } else { strRet[0] = '-'; } swap(left, right); swap(Lsize, Rsize); strRet.resize(Lsize); } if (Lsize > Rsize) { strRet[0] = left[0]; } //逐位相减 for (int iIdx = 1; iIdx < Lsize; iIdx++) { int cRet = left[Lsize - iIdx] - '0'; if (iIdx < Rsize) { cRet -= right[Rsize - iIdx] - '0'; } if (cRet < 0) { cRet += 10; left[Lsize - iIdx - 1] -= 1; } strRet[Lsize - iIdx] = cRet + '0'; } return strRet; } BigData BigData::operator-(const BigData& bigData) { if (!_IsINT64Overflow() && !bigData._IsINT64Overflow()) { if (_strData[0] == bigData._strData[0]) { return BigData(_value - bigData._value); } else { if (('+' == _strData[0] && MAX_INT_64 + bigData._value >= _value) || ('-' == _strData[0] && MIN_INT_64 + bigData._value <= _value)) { return BigData(_value - bigData._value); } } } // 超出 if (_strData[0] != bigData._strData[0]) { std::string strRet = Add(_strData, bigData._strData); strRet[0] = _strData[0]; return BigData(strRet); } return BigData(Sub(_strData, bigData._strData)); } BigData BigData::operator*(const BigData& bigData) { //两个数都没有溢出 if (!_IsINT64Overflow() && !bigData._IsINT64Overflow()) { //同号相乘不会溢出 if (_strData[0] == bigData._strData[0]) { if ((_strData[0] == '+'&&MAX_INT_64 / _value >= bigData._value) || (_strData[0] == '-'&&MAX_INT_64 / _value <= bigData._value)) { return (_value * bigData._value); } } //异号相乘不会溢出 else { if ((_strData[0] == '-'&&MIN_INT_64 / _value >= bigData._value) || (_strData[0] == '+'&&MIN_INT_64 / _value <= bigData._value)) { return (_value * bigData._value); } } } //至少有一个溢出或者相乘结果溢出 return (BigData(Mul(_strData, bigData._strData))); } string BigData::Mul(string left, string right) { int Lsize = left.size(); int Rsize = right.size(); if (Lsize < Rsize) { swap(left, right); swap(Lsize, Rsize); } string strRet; strRet.resize(Lsize + Rsize - 1, '0'); strRet[0] = '+'; //逐位相乘 int cstep = 0; string tmp; tmp.resize(Lsize + 1, '0'); string Inistring(tmp); for (int RIdx = 1; RIdx < Rsize; RIdx++) { for (int LIdx = 1; LIdx < Lsize; LIdx++) { int cRet = right[Rsize - RIdx] - '0'; cRet *= left[Lsize - LIdx] - '0'; cRet += cstep; //if (cRet>=10) //{ cstep = cRet / 10; cRet = cRet % 10; //} tmp[Lsize - LIdx + 1] = cRet + '0'; } tmp[1] = cstep + '0'; tmp[0] = '+'; tmp.append(RIdx-1, '0'); strRet = (BigData(tmp)+ BigData(strRet))._strData;//相加结果保存在strRet中 tmp = Inistring; cstep = 0; } if (left[0] != right[0]) strRet[0] = '-'; return strRet; } BigData BigData::operator/(const BigData& bigData) { return BigData(Div(_strData, bigData._strData)); assert(!(bigData._value == 0 && _strData == "+")); BigData b("0"); //被除数为零 if (_value == 0&&_strData=="+") { return b; } if ((!_IsINT64Overflow())&& (!bigData._IsINT64Overflow())) { return _value / bigData._value; } if (_strData.size() < bigData._strData.size()) { return b; } else if (_strData.size() == bigData._strData.size()) { if (strcmp((char*)_strData.c_str() + 1, (char*)bigData._strData.c_str() + 1) < 0) { return b; } else if (strcmp((char*)_strData.c_str() + 1, (char*)bigData._strData.c_str() + 1) == 0) { if (_strData[0] == bigData._strData[0]) { return BigData(1); } else return BigData(-1); } else { INT_64 ret = 0; ret = DivSub(_strData, (string)bigData._strData); return BigData(ret)._strData; } } else return BigData(Div(_strData, bigData._strData)); } bool BigData::IsLessThanDiv(string& tmp,string& Right) { BigData ret = BigData(tmp.c_str() + 1) - BigData(Right.c_str() + 1); if (ret._strData[0] == '-') return true; return false; } int BigData::DivSub(string& tmp, string& pRight) { int count = 0; char cRet = 0; while (!IsLessThanDiv(tmp, pRight)) { count++; tmp = Sub(tmp, pRight); } return count; } string BigData::Div(string left, string right) { string strRet; strRet.resize(1); if (left[0] != right[0]) { strRet[0] = '-'; } else strRet[0] = '+'; string tmp; tmp.resize(right.size(), '0'); int iIdx = 0; for (iIdx = 0; iIdx < right.size(); iIdx++) { tmp[iIdx] = left[iIdx]; } int count = 0; //此时iIdx=right,size(); while (iIdx < left.size()) { //不能减,再取一位 if (IsLessThanDiv(tmp, right)) { strRet.append(1, '0'); tmp.append(1, left[iIdx++]); continue; } //能除,确定商 count = DivSub(tmp, right); char c = count + '0'; strRet.append(1, c); tmp.append(1, left[iIdx++]); } //将余下的tmp计算一次 count = DivSub(tmp, right); char c = count + '0'; strRet.append(1, c); return strRet; }
最后是一组简单的测试函数
#include"BigData.h" using namespace std; void funtest1() { string s1 = "000009223372036854775808"; string s2 = "10"; BigData bd1(s1); cout << bd1 << endl; BigData bd2(10); cout << bd2 << endl; BigData bd3 = bd1 + bd2; cout << bd3 << endl; } void funtest2() { string s1 ="+3333666666666667777777777777333"; string s2 ="+999999999999999999999999999999"; BigData bd1(s1); cout << bd1 << endl; BigData bd2(s2); cout << bd2 << endl; BigData bd3 = bd1 - bd2; cout << bd3 << endl; } void funtest3() { string s1 = "-999999999999999999999999"; string s2 = "-222222222222222222222"; BigData bd1(s1); cout << bd1 << endl; BigData bd2(s2); cout << bd2 << endl; BigData bd3 = bd1 * bd2; cout << bd3 << endl; } void funtest4() { string s1 = "-990000000000000000099"; string s2 = "33"; //-30303030303030303030303030303030303 //-3030303030303030303030303030303030 BigData bd1(s1); cout << bd1 << endl; BigData bd2(s2); cout << bd2 << endl; BigData bd3 = bd1 / bd2; cout << bd3 << endl; } int main() { //funtest1(); //funtest2(); //funtest3(); funtest4(); system("pause"); return 0; }
代码逻辑都很简单,只是写起来比较费事,所以如此冗长。
相关文章推荐
- wait 与 waitpid
- UVALive 6885 Flowery Trails 最短路枚举
- codeforces 360 D - Remainders Game
- POJ 3421 X-factor Chains (整数分解+组合数)
- UVA - 573 The Snail
- UVA - 253 Cube painting
- 整合 ElasticSearch 到现有 Rails 项目
- ACM--元辅音--HDOJ 1039--Easier Done Than Said?--字符串
- B. Remainders Game
- 调用http://apistore.baidu.com网站的接口
- Kafka设计解析(三)- Kafka High Availability (下)
- Kafka设计解析(二)- Kafka High Availability (上)
- CDH 与 CM 环境搭建,配置,集成大数据服务
- UVA - 253 Cube painting
- 模仿AIDL实现进程间通信
- Spark Stage 的划分
- 10.Examine the following statement that is used to modify the constraint on the SALES table:
- wait、notify、notifyAll和Condition
- 物联网加密
- 浅谈工业级物联网项目架构设计及实施