大数项目:用字符串表示超过内存表示范围的大数据并实现四则运算
来源:互联网 发布:java格式化html代码 编辑:程序博客网 时间:2024/05/06 04:34
原理很简单,直接上代码。
这里是初级版,效率低下,代码复杂不明了。只是尽可能的实现功能,改进版将在后续推出。
这里是头文件 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 -9223372036854775807INT_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;}
代码逻辑都很简单,只是写起来比较费事,所以如此冗长。
1 0
- 大数项目:用字符串表示超过内存表示范围的大数据并实现四则运算
- 大数相乘解决办法,用字符串表示的大数
- 算法:大数相乘,用字符串表示
- 用字符串表示大整数
- delphi中实现用字符串表示并操作控件的方法。
- 计算出用字符串表示的数学表达式的值
- 计算出用字符串表示的数学表达式的值
- 用字符串表示十进制数
- 数据表示范围
- 用字符串数组实现的大数运算
- float数据的内存表示
- 串的内存表示
- 每天一道LeetCode-----将用数组表示的整数加一,两个用字符串表示的(二进制)数相加
- 用字符串实现大数相乘
- 分数的表示和四则运算
- char表示的范围
- sql server中十六进制用字符串表示
- 415. Add Strings--两个用字符串表示的数字相加
- 点击升级小心形-仿映客直播点赞
- 器普语言代码欣赏-全中文编程时代来临
- 对程序的一点想法
- 17.Note the functionalities of various background processes:
- 最小生成树(minimum spanning tree)问题的两种解法
- 大数项目:用字符串表示超过内存表示范围的大数据并实现四则运算
- centos下安装JDK
- BZOJ4568 SCOI2016 幸运数字 倍增的思想维护线性基(线性基详解)
- Android基础知识--BroadcastReceiver
- Spark1.6.1平台搭建(hadoop-2.7.2 scala-2.11.8)
- JAVA开发工具Intellij Idea 破解
- <第一行代码>笔记二
- 编程珠玑第九|十章学习总结
- Android获取当前位置(GPS和网络定位)