|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 bin554385863 于 2020-1-7 04:20 编辑
#include "E:\Users\admin\Documents\VScode\Code\My Class\lnum\lnum.cpp"
lnum fact(const lnum &n)
{
lnum fact = "1";
for (lnum i = "1"; i <= n; i++)
{
fact *= i;
}
return fact;
}
int main(int argc, char const *argv[])
{
lnum a = "1";
for (lnum i = "10"; i != "110"; i += "10")
{
std::cout << i<<"! = "<<fact(i) << std::endl;
}
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-bln4vusc.bgf --stdout=Microsoft-MIEngine-Out-pkxxzoxc.0jt --stderr=Microsoft-MIEngine-Error-tn53w3yl.5hv --pid=Microsoft-MIEngine-Pid-ddmgmwek.eog --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi
10! = 3628800
20! = 2432902008176640000
30! = 265252859812191058636308480000000
40! = 815915283247897734345611269596115894272000000000
50! = 30414093201713378043612608166064768844377641568960512000000000000
60! = 8320987112741390144276341183223364380754172606361245952449277696409600000000000000
70! = 11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000
80! = 71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000
90! = 1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000
100! = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
E:\Users\admin\Documents\VScode\Code>
完整代码
当字符串出现其他非数字字符时(有效的负号和小数点除外)全部按"0"处理.
代码不能识别顺序错误的数字字符串,如"0005000"这样的数字字符串,请输入正确的数字字符串如:"1365458", "-0.1234566"等等(可以实现在构造对象时清除无效零的功能,相应函数已经写好,但这样会在计算带小数位的乘法时造成额外的逻辑判断)
已经重载输出流符号<<和输入流符号>>,可以向基础类型一样使用cout/cin进行输入输出.
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
{
struct ndata
{
int sign;
string nstr;
vector<int> nvec;
size_t isize, dsize;
};
struct align
{
vector<int> first, second;
};
private:
static size_t pre;
ndata data;
//(0)判断是否含有小数点
const bool hasDecPoint(const string &s) const;
//(1)判断字符串是否有效
const bool isInvalidStr(const string &s) const;
//(2)判断字符串元素是否全为零
const bool isStrElemAllZero(const string &s) const;
//(3)清除无效的零
const string clearInvalidZero(const string &s) const;
//(4)转换数组
const vector<int> strToVec(const string &s) const;
//(-4)转换字符串
const string vecToStr(const vector<int> &vint, int sgn, size_t dsz) const;
//(5)提取信息
const ndata getInfo(const string &s) const;
//(6)小数位对齐
align dAlign(const lnum &l) const;
//(7)整体对齐
align wAlign(const lnum &l) const;
//(8)满十进一
void carry(vector<int> &v) const;
//(9)借一补十
void borrow(vector<int> &v) const;
//(10)输出设置
const string setPrint() const;
//(11)lnum*n
const lnum operator*(const int &n) const;
public:
lnum(const char *cstr = "0") : data(getInfo(cstr))
{
}
lnum(const string &s):data(getInfo(s)){}
void showinfo() const;
static void setprecision(const size_t p);
//(1)>号
const bool operator>(const lnum &l) const;
//(2)==
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;
//(5)!=
const bool operator!=(const lnum &l) const;
//(6)+
const lnum operator+(const lnum &l) const;
//(7)-反转正负
const lnum operator-() const;
//(7.5)-
const lnum operator-(const lnum &l) const;
//(8)+=
const lnum &operator+=(const lnum &l);
//(9)++
const lnum &operator++(const int i);
//(10)-=
const lnum &operator-=(const lnum &l);
//(11)--
const lnum &operator--(const int i);
//(12)lnum*lnum
const lnum operator*(const lnum &l) const;
//(10)*=
const lnum &operator*=(const lnum &l);
//(F)<<
friend ostream &operator<<(ostream &os, const lnum &l);
//(F)>>
friend istream &operator>>(istream &is, lnum &l);
~lnum(){}
};
size_t lnum::pre = 6;
#endif
方法实现
lnum.cpp
#include "E:\Users\admin\Documents\VScode\Code\My Class\lnum\lnum.h"
//(0)判断是否含有小数点
const bool lnum::hasDecPoint(const string &s) const
{
return int(s.find('.')) > -1 ? true : false;
}
//(1)判断字符串是否有效
const bool lnum::isInvalidStr(const string &s) const
{
bool f = true;
string str = s;
if (str[0] == '-')
{
str.erase(0, 1);
}
if (!hasDecPoint(str))
{
for (char c : str)
{
if (!isdigit(c))
{
f = false;
break;
}
}
}
else
{
size_t dpinx = str.find('.');
f = (dpinx == 0) || (dpinx == (str.size() - 1)) || (dpinx != str.rfind('.')) ? false : true;
str.erase(dpinx, 1);
for (char c : str)
{
if (!isdigit(c))
{
f = false;
break;
}
}
}
return f;
}
//(2)判断字符串元素是否全为零
const bool lnum::isStrElemAllZero(const string &s) const
{
string str = s;
str[0] == '-' ? str.erase(0, 1) : str;
hasDecPoint(str) || false ? str.erase(str.find('.'), 1) : str;
return str == string(str.size(), '0') ? true : false;
}
//(3)清除无效的零
const string lnum::clearInvalidZero(const string &s) const
{
string str = s;
if (isInvalidStr(s))
{
size_t i = 0;
if (str[0] == '-')
{
str.erase(0, 1);
}
if (!hasDecPoint(s))
{
size_t sz = str.size();
while (i != sz)
{
if (str[i] != '0')
{
break;
}
i++;
}
if (i == sz)
{
str.erase(0, i - 1);
}
else if (i > 0)
{
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 if (i > 0)
{
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 != "0")
{
str.insert(0, 1, '-');
}
return str;
}
//(4)转换数组
const vector<int> lnum::strToVec(const string &s) const
{
vector<int> vint;
string str = s;
str[0] == '-' ? str.erase(0, 1) : str;
hasDecPoint(str) > false ? str.erase(str.find('.'), 1) : str;
for (char c : str)
{
vint.push_back(c - 48);
}
return vint;
}
//(-4)转换字符串
const string lnum::vecToStr(const vector<int> &vint, int sgn, size_t dsz) const
{
string str;
for (int i : vint)
{
str.push_back(i + 48);
}
if (str != "0")
{
dsz == 0 ? str : str.insert(str.size() - dsz, 1, '.');
sgn == -1 ? str.insert(0, 1, '-') : str;
}
return str;
}
//(5)提取信息
const lnum::ndata lnum::getInfo(const string &s) const
{
ndata ndt = {0, "0", {0}, 1, 0};
if (isInvalidStr(s))
{
ndt.nstr = s;
ndt.sign = ndt.nstr != "0" ? (ndt.nstr[0] == '-' ? -1 : 1) : 0;
ndt.dsize = hasDecPoint(ndt.nstr) || false ? ndt.nstr.size() - ndt.nstr.find('.') - 1 : 0;
ndt.nvec = strToVec(ndt.nstr);
ndt.isize = ndt.nvec.size() - ndt.dsize;
}
return ndt;
}
//(6)小数位对齐
lnum::align lnum::dAlign(const lnum &l) const
{
align agn;
vector<int> &f = agn.first, &s = agn.second;
f = data.nvec;
s = l.data.nvec;
const size_t &fds = data.dsize, &sds = l.data.dsize;
fds > sds ? s.insert(s.end(), fds - sds, 0) : f.insert(f.end(), sds - fds, 0);
return agn;
}
//(7)整体对齐
lnum::align lnum::wAlign(const lnum &l) const
{
align &&agn = this->dAlign(l);
vector<int> &f = agn.first, &s = agn.second;
const size_t &fws = data.isize, &sws = l.data.isize;
fws > sws ? s.insert(s.begin(), fws - sws, 0) : f.insert(f.begin(), sws - fws, 0);
return agn;
}
//(8)满十进一
void lnum::carry(vector<int> &v) const
{
v.insert(v.begin(), 1, 0);
const size_t s = v.size();
for (size_t i = s - 1; i != 0; i--)
{
int t = v[i];
v[i] = t % 10;
v[i - 1] += t / 10;
}
if (v[0] == 0)
{
v.erase(v.begin(), v.begin() + 1);
}
}
//(9)借一补十
void lnum::borrow(vector<int> &v) const
{
const size_t s = v.size();
for (size_t i = 1; i < s; i++)
{
v[i - 1] -= 1;
v[i] += 10;
}
}
//(10)输出设置
const string lnum::setPrint() const
{
const size_t &tds = data.dsize;
string str = data.nstr;
if (pre == 0)
{
if (tds != 0)
{
str.erase(str.find('.'));
}
}
else if (tds > pre)
{
str.erase(str.size() - (tds - pre));
}
return clearInvalidZero(str);
}
//(11)lnum*n
const lnum lnum::operator*(const int &n) const
{
vector<int> t = data.nvec;
for (int &i : t)
{
i *= n;
}
carry(t);
lnum r = vecToStr(t, data.sign, data.dsize);
return r;
}
//==========================================================================
//(0)显示信息
void lnum::showinfo() const
{
std::cout << "正/负/零: " << data.sign << "\n"
<< "原始数字: " << data.nstr << "\n"
<< "数组元素: ";
for (int i : data.nvec)
{
std::cout << i << " ";
}
std::cout << std::endl;
std::cout << "整数位数: " << data.isize << "\n"
<< "小数位数: " << data.dsize << std::endl;
}
void lnum::setprecision(const size_t p)
{
pre = p;
}
//(1)>号
const bool lnum::operator>(const lnum &l) const
{
bool f = true;
const int &tsgn = data.sign, &lsgn = l.data.sign;
if (tsgn < lsgn)
{
f = false;
}
else if (tsgn == lsgn)
{
const align &agn = this->wAlign(l);
f = agn.first > agn.second;
if (tsgn == -1)
{
f = !f;
}
}
return f;
}
//(2)==
const bool lnum::operator==(const lnum &l) const
{
return (data.sign == l.data.sign) && (data.nvec == l.data.nvec);
}
//(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);
}
//(5.5)!=
const bool lnum::operator!=(const lnum &l) const
{
return !(*this == l);
}
//(6)+
const lnum lnum::operator+(const lnum &l) const
{
lnum r;
if (*this != (-l))
{
align agn = this->wAlign(l);
vector<int> &fst = agn.first,
&sec = agn.second,
&greater = fst >= sec ? fst : sec,
&less = sec <= fst ? sec : fst;
const int &tsgn = data.sign,
&lsgn = l.data.sign;
const size_t &sz = fst.size();
for (size_t i = 0; i < sz; i++)
{
greater[i] += (lsgn * tsgn) * less[i];
}
int sgn = 1;
if (tsgn == lsgn)
{
sgn = tsgn;
}
else if (tsgn != lsgn)
{
sgn = ((greater == fst && tsgn < lsgn) || (less == fst && tsgn > lsgn)) || false ? -1 : sgn;
}
if (tsgn * lsgn == -1)
{
borrow(greater);
}
carry(greater);
size_t dsz = data.dsize >= l.data.dsize ? data.dsize : l.data.dsize;
r = vecToStr(greater, sgn, dsz);
}
return r;
}
//(7)-反转正负
const lnum lnum::operator-() const
{
lnum r = *this;
if (data.sign != 0)
{
r.data.sign = -data.sign;
r.data.nstr = vecToStr(data.nvec, -data.sign, data.dsize);
}
return r;
}
//(7.5)-
const lnum lnum::operator-(const lnum &l) const
{
return *this + (-l);
}
//(8)+=
const lnum &lnum::operator+=(const lnum &l)
{
return *this = *this + l;
}
//(9)++
const lnum &lnum::operator++(const int i)
{
return *this = *this + "1";
}
//(10)-=
const lnum &lnum::operator-=(const lnum &l)
{
return *this = *this + (-l);
}
//(11)--
const lnum &lnum::operator--(const int i)
{
return *this = *this + "-1";
}
//(12)lnum*lnum
const lnum lnum::operator*(const lnum &l) const
{
lnum r;
const int &tsgn = data.sign,
&lsgn = l.data.sign;
if (tsgn * lsgn == 0)
{
r = "0";
}
else
{
const vector<int> &tvec = data.nvec,
&lvec = l.data.nvec;
const size_t &tsz = data.dsize,
&lsz = l.data.dsize,
&tvsz = tvec.size(),
&lvsz = lvec.size(),
&shrtsz = tvsz <= lvsz ? tvsz : lvsz;
lnum loong = tvsz >= lvsz ? *this : l;
const vector<int> &shrtv = lvsz <= tvsz ? lvec : tvec;
vector<int> &lovec = loong.data.nvec,
&rvec = r.data.nvec;
for (size_t i = shrtsz - 1; i != -1; i--)
{
r += loong * shrtv[i];
if (i > 0)
{
lovec.push_back(0);
}
}
r = vecToStr(rvec, tsgn * lsgn, tsz + lsz);
}
return r;
}
//(10)*=
const lnum &lnum::operator*=(const lnum &l)
{
return *this = *this * l;
}
//(F)<<
ostream &operator<<(ostream &os, const lnum &l)
{
os << l.setPrint();
return os;
}
//(F)>>
istream &operator>>(istream &is, lnum &l)
{
string str;
(std::cin >> str).get();
l = str;
return is;
}
|
|