|
楼主 |
发表于 2020-1-3 18:08:54
|
显示全部楼层
__优化代码
__添加算法
__实现精度输出
lnum.cpp
#ifndef LNUM_H
#define LNUM_H
#include <iostream>
#include <string>
#include <vector>
using std::istream;
using std::ostream;
using std::string;
using std::vector;
class lnum
{
typedef vector<int> vecint;
struct attr
{
string str = "0";
int sign = 0;
vecint vec = {0};
size_t nsize = 1, dsize = 0;
};
struct align
{
vecint first, second;
};
private:
attr num;
static size_t precision;
//初始化构造函数的数据
const attr InitData(const string &s);
//判断是否有效的数字字符串
const bool IsNumStr(const string &s) const;
//判断字符串元素是否全为'0'
const bool IsStrElemZero(const string &s) const;
//清除无效的0
const string ClearStrZero(const string &s) const;
//获取正负符号
const int getSign(const string &s) const;
//获取数组
const vecint Str2Vec(const string &s) const;
//获取数字字符串
const string Vec2Str(const vecint &v, int sgn, size_t dps) const;
//获取小数位数
const size_t getDsize(const string &s) const;
//整体对齐
const align nAlign(const lnum &l) const;
//小数位对齐
const align dAlign(const lnum &l) const;
//满十进一
void Carry(vecint &v) const;
//借一
void Borrow(vecint &v) const;
//数组乘整数
lnum operator*(const int i) const;
//输出字符串
const string outPutStr() const;
public:
lnum(const char *cstr = "0") : num(InitData(cstr)) {}
lnum(const string &s) : num(InitData(s)) {}
lnum(const lnum &l) : num(l.num) {}
void showinfo() const;
//(1)重载>
const bool operator>(const lnum &l) const;
//(2)重载==
const bool operator==(const lnum &l) const;
//(2.5)重载!=
const bool operator!=(const lnum &l) const;
//(3)重载>=
const bool operator>=(const lnum &l) const;
//(4)重载<
const bool operator<(const lnum &l) const;
//(5)重载<=
const bool operator<=(const lnum &l) const;
//(6)重载+
const lnum operator+(const lnum &l) const;
//(7)重载-,反转正负
const lnum operator-() const;
//(8)重载-
const lnum operator-(const lnum &l) const;
//(9)重载+=
const lnum &operator+=(const lnum &l);
//(10)重载++
const lnum &operator++();
//(11)重载-=
const lnum &operator-=(const lnum &l);
//(12)重载--
const lnum &operator--();
//(13)前置++
friend const lnum &operator++(lnum &l, const int i);
//(14)前置--
friend const lnum &operator--(lnum &l, const int i);
void static setprecision(const unsigned i);
friend ostream &operator<<(ostream &os, const lnum &l);
friend istream &operator>>(istream &is, lnum &l);
virtual ~lnum() {}
};
size_t lnum::precision = 0;
#endif
lnum.cpp
#include "E:\Users\admin\Documents\VScode\Code\My Class\largenum\lnum.h"
//(1)初始化构造函数的数据
const lnum::attr lnum::InitData(const string &s)
{
attr n = {ClearStrZero(s),
getSign(n.str),
Str2Vec(n.str),
n.vec.size(),
getDsize(n.str)};
return n;
}
//(2)判断是否有效的数字字符串
const bool lnum::IsNumStr(const string &s) const
{
bool f = true;
string str = s;
if (str[0] == '-')
{
str.erase(0, 1);
}
if (int(str.find('.')) == -1)
{
for (char &c : str)
{
if (!isdigit(c))
{
f = false;
break;
}
}
}
else
{
if ((str.find('.') == 0) || (str.find('.')) == (str.size() - 1) || (s.find('.') != s.rfind('.')))
{
f = false;
}
else
{
str.erase(str.find('.'), 1);
for (char &c : str)
{
if (!isdigit(c))
{
f = false;
break;
}
}
}
}
return f;
}
//(3)判断字符串元素是否全为'0'
const bool lnum::IsStrElemZero(const string &s) const
{
bool f = false;
string str = s;
if (str[0] == '-')
{
str.erase(0, 1);
}
if (int(s.find('.')) != -1)
{
str.erase(str.find('.'), 1);
}
if (str == string(str.size(), '0'))
{
f = true;
}
return f;
}
//(4)清除无效的0
const string lnum::ClearStrZero(const string &s) const
{
string str = "0";
if (IsNumStr(s) && (!IsStrElemZero(s)))
{
str = s;
if (str[0] == '-')
{
str.erase(0, 1);
}
size_t i = 0;
if (int(s.find('.')) == -1)
{
size_t sz = str.size();
while (i != sz)
{
if (str[i] != '0')
{
break;
}
i++;
}
if (i == sz)
{
str.erase(0, i - 1);
}
else
{
str.erase(0, i);
}
}
else
{
i = 0;
while (str[i] != '.')
{
if (str[i] != '0')
{
break;
}
i++;
}
if (i == str.find('.'))
{
str.erase(0, i - 1);
}
else
{
str.erase(0, i);
}
i = str.size() - 1;
while (str[i] != '.')
{
if (str[i] != '0')
{
break;
}
i--;
}
if (i == str.find('.'))
{
str.erase(i);
}
else if (i < str.size() - 1)
{
str.erase(i + 1);
}
}
if (s[0] == '-')
{
str.insert(0, 1, '-');
}
}
return str;
}
//(5)获取正负符号
const int lnum::getSign(const string &s) const
{
int sgn = 0;
if (s != "0")
{
sgn = s[0] == '-' ? -1 : 1;
}
return sgn;
}
//(6)获取数组
const lnum::vecint lnum::Str2Vec(const string &s) const
{
vecint v = {0};
if (IsNumStr(s))
{
string str = s;
if (str[0] == '-')
{
str.erase(0, 1);
}
if (int(s.find('.')) != -1)
{
str.erase(str.find('.'), 1);
}
v.clear();
for (char &c : str)
{
v.push_back(c - 48);
}
}
return v;
}
//(7)获取数字字符串
const string lnum::Vec2Str(const vecint &v, int sgn, size_t dps) const
{
string str = "0";
if (sgn != 0)
{
str.clear();
for (const int &i : v)
{
str.push_back(i + 48);
}
if (dps != 0)
{
str.insert(str.size() - dps, 1, '.');
}
if (sgn == -1)
{
str.insert(0, 1, '-');
}
}
return str;
}
//(8)获取小数位数
const size_t lnum::getDsize(const string &s) const
{
size_t dps = 0;
if (s.find('.') != -1)
{
dps = s.size() - s.find('.') - 1;
}
return dps;
}
//(9)整体对齐
const lnum::align lnum::nAlign(const lnum &l) const
{
align agn;
const vecint &tvec = num.vec, &lvec = l.num.vec;
vecint &fst = agn.first, &sec = agn.second;
const size_t &tdps = num.dsize, &ldps = l.num.dsize;
fst = tvec;
sec = lvec;
tdps > ldps ? sec.insert(sec.end(), tdps - ldps, 0) : fst.insert(fst.end(), ldps - tdps, 0);
const size_t &fsz = fst.size(), &ssz = sec.size();
fsz > ssz ? sec.insert(sec.begin(), fsz - ssz, 0) : fst.insert(fst.begin(), ssz - fsz, 0);
return agn;
}
//(10)小数位对齐
const lnum::align lnum::dAlign(const lnum &l) const
{
align agn;
vecint &fst = agn.first, &sec = agn.second;
const size_t &tdps = num.dsize, &ldps = l.num.dsize;
fst = num.vec;
sec = l.num.vec;
tdps > ldps ? sec.insert(sec.end(), tdps - ldps, 0) : fst.insert(fst.end(), ldps - tdps, 0);
return agn;
}
//满十进一
void lnum::Carry(vecint &v) const
{
v.insert(v.begin(), 1, 0);
size_t sz = v.size();
for (size_t i = sz - 1; i > 0; i--)
{
int t = v[i];
v[i] = t % 10;
v[i - 1] += t / 10;
}
}
//借一
void lnum::Borrow(vecint &v) const
{
size_t s = v.size();
for (size_t i = 1; i < s; i++)
{
v[i - 1] -= 1;
v[i] += 10;
}
}
//数组乘整数
lnum lnum::operator*(const int i) const
{
lnum r = "0";
if (num.sign != 0)
{
r = *this;
attr &rum = r.num;
for (int &k : rum.vec)
{
k *= i;
}
Carry(rum.vec);
r = Vec2Str(rum.vec, rum.sign, rum.dsize);
}
return r;
}
//输出字符串
const string lnum::outPutStr() const
{
string str = num.str;
const size_t &ds = num.dsize;
if (precision < ds)
{
if (precision == 0)
{
str.erase(str.size() - ds - 1);
}
else
{
str.erase(str.size() - ds);
}
}
return str;
}
/***********************************************************************/
//数字属性
void lnum::showinfo() const
{
std::cout << "正/负/零: " << num.sign << "\n"
<< "原始字符: " << num.str << "\n"
<< "数字元素: ";
for (const int &i : num.vec)
{
std::cout << i << " ";
}
std::cout << std::endl;
std::cout << "数字长度: " << num.nsize << "\n"
<< "小数位数: " << num.dsize << std::endl;
}
//(1)重载>
const bool lnum::operator>(const lnum &l) const
{
bool f = true;
const align agn = this->nAlign(l);
const vecint &fst = agn.first,
&sec = agn.second;
const int tsgn = num.sign, &lsgn = l.num.sign;
if (tsgn < lsgn)
{
f = false;
}
else if (tsgn == lsgn)
{
f = fst > sec;
if (tsgn < 0)
{
f = !f;
}
}
return f;
}
//(2)重载==
const bool lnum::operator==(const lnum &l) const
{
const align agn = this->nAlign(l);
const vecint &fst = agn.first,
&sec = agn.second;
return (num.sign == l.num.sign) && (fst == sec);
}
//(2.5)重载!=
const bool lnum::operator!=(const lnum &l) const
{
return !(*this == l);
}
//(3)重载>=
const bool lnum::operator>=(const lnum &l) const
{
return (*this == l || *this > l);
}
//(4)重载<
const bool lnum::operator<(const lnum &l) const
{
return !(*this >= l);
}
//(5)重载<=
const bool lnum::operator<=(const lnum &l) const
{
return (*this < l || *this == l);
}
//(6)重载+
const lnum lnum::operator+(const lnum &l) const
{
lnum r = "0";
const int &tsgn = num.sign, &lsgn = l.num.sign;
if ((tsgn == 0 && lsgn != 0) || (tsgn != 0 && lsgn == 0))
{
r = (tsgn != 0) > (lsgn != 0) ? *this : l;
}
else if (*this != (-l))
{
int sgn = -1;
const size_t &tds = num.dsize, &lds = l.num.dsize,
&ds = tds > lds ? tds : lds;
align agn = this->nAlign(l);
vecint &fst = agn.first, &sec = agn.second, t = fst >= sec ? fst : sec;
size_t s = fst.size();
for (size_t i = 0; i < s; i++)
{
t[i] += ((tsgn * lsgn) * ((sec <= fst ? sec : fst)[i]));
}
if ((fst < sec && tsgn < lsgn) || (sec < fst && lsgn < tsgn) || (tsgn == lsgn && tsgn == 1))
{
sgn = 1;
}
if (tsgn!=lsgn)
{
Borrow(t);
}
Carry(t);
attr &rum = r.num;
rum.str = ClearStrZero(Vec2Str(t, sgn, ds));
rum.vec = Str2Vec(rum.str);
rum.nsize = rum.vec.size();
rum.dsize = ds;
rum.sign = sgn;
}
return r;
}
//(7)重载-,反转正负
const lnum lnum::operator-() const
{
lnum r = *this;
r.num.sign = -num.sign;
r.num.str = Vec2Str(num.vec, -num.sign, num.dsize);
return r;
}
//(8)重载-
const lnum lnum::operator-(const lnum &l) const
{
lnum r;
const int &tsgn = num.sign, &lsgn = l.num.sign;
if (tsgn == 0 && lsgn != 0)
{
r = -l;
}
else if (lsgn == 0 && tsgn != 0)
{
r = *this;
}
else if (lsgn != 0 && tsgn != 0)
{
r = *this + (-l);
}
return r;
}
//(9)重载+=
const lnum &lnum::operator+=(const lnum &l)
{
*this = *this + l;
return *this;
}
//(10)重载++
const lnum &lnum::operator++()
{
return *this += "1";
}
//(11)重载-=
const lnum &lnum::operator-=(const lnum &l)
{
*this = *this - l;
return *this;
}
//(12)重载--
const lnum &lnum::operator--()
{
return *this -= "1";
}
//(13)前置++
const lnum &operator++(lnum &l, const int i)
{
return ++l;
}
//(14)前置--
const lnum &operator--(lnum &l, const int i)
{
return --l;
}
void lnum::setprecision(const size_t i)
{
lnum::precision = i;
}
ostream &operator<<(ostream &os, const lnum &l)
{
os << l.outPutStr();
return os;
}
istream &operator>>(istream &is, lnum &l)
{
string inPutStr;
(is >> inPutStr).get();
l = inPutStr;
return is;
}
=====================================================================
main.cpp
#include "E:\Users\admin\Documents\VScode\Code\My Class\largenum\lnum.cpp"
#include <ctime>
int main(int argc, char const *argv[])
{
lnum::setprecision(3);
lnum a, b;
srand(time(NULL));
char m[7], n[7];
n[6] = m[6] = '\0';
int k = 0;
while (k != 10)
{
for (size_t i = 0; i < 6; i++)
{
m[i] = rand() % 9 + 48;
n[i] = rand() % 9 + 48;
}
m[rand() % 2 + 2] = '.';
n[rand() % 2 + 2] = '.';
if (k % 2 == 0)
{
m[0] = '-';
}
if (k%3 == 0)
{
n[0] = '-';
}
a = m;
b = n;
std::cout << "第" << k << "组"
<< "\n"
<< "a = " << a << " "
<< "b = " << b << "\n--------------------------------------------------\n"
<< "a > b: " << std::boolalpha << (a > b) << "\n"
<< "a == b: " << (a == b) << "\n"
<< "a < b: " << (a < b) << "\n--------------------------------------------------------\n"
<< "a + b = " << (a + b) << "\n"
<< "a - b = " << (a - b) << "\n=======================================================\n";
k++;
}
return 0;
}
=================================================================================
Microsoft Windows [版本 10.0.18363.535]
(c) 2019 Microsoft Corporation。保留所有权利。
E:\Users\admin\Documents\VScode\Code>c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-yrdvjqxw.52e --stdout=Microsoft-MIEngine-Out-l05gzt3v.anm --stderr=Microsoft-MIEngine-Error-cyag0fjm.qse --pid=Microsoft-MIEngine-Pid-42rglrua.ou0 --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi
第0组
a = -3.08 b = -38.58
--------------------------------------------------
a > b: true
a == b: false
a < b: false
--------------------------------------------------------
a + b = -41.66
a - b = 35.5
=======================================================
第1组
a = 407.56 b = 601.42
--------------------------------------------------
a > b: false
a == b: false
a < b: true
--------------------------------------------------------
a + b = 1008.98
a - b = -193.86
=======================================================
第2组
a = -6.366 b = 72.44
--------------------------------------------------
a > b: false
a == b: false
a < b: true
--------------------------------------------------------
a + b = 66.074
a - b = -78.806
=======================================================
第3组
a = 652.88 b = -1.731
--------------------------------------------------
a > b: true
a == b: false
a < b: false
--------------------------------------------------------
a + b = 651.149
a - b = 654.611
=======================================================
第4组
a = -1.467 b = 745.22
--------------------------------------------------
a > b: false
a == b: false
a < b: true
--------------------------------------------------------
a + b = 743.753
a - b = -746.687
=======================================================
第5组
a = 842.55 b = 63.016
--------------------------------------------------
a > b: true
a == b: false
a < b: false
--------------------------------------------------------
a + b = 905.566
a - b = 779.534
=======================================================
第6组
a = -46.87 b = -4.057
--------------------------------------------------
a > b: false
a == b: false
a < b: true
--------------------------------------------------------
a + b = -50.927
a - b = -42.813
=======================================================
第7组
a = 10.748 b = 752.88
--------------------------------------------------
a > b: false
a == b: false
a < b: true
--------------------------------------------------------
a + b = 763.628
a - b = -742.132
=======================================================
第8组
a = -1.506 b = 804.61
--------------------------------------------------
a > b: false
a == b: false
a < b: true
--------------------------------------------------------
a + b = 803.104
a - b = -806.116
=======================================================
第9组
a = 2.626 b = -6.542
--------------------------------------------------
a > b: true
a == b: false
a < b: false
--------------------------------------------------------
a + b = -3.916
a - b = 9.168
=======================================================
E:\Users\admin\Documents\VScode\Code> |
|