鱼C论坛

 找回密码
 立即注册
查看: 1209|回复: 6

[技术交流] 字符串计算第二版

[复制链接]
发表于 2020-1-3 02:33:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 bin554385863 于 2020-1-3 16:15 编辑

lnum.h
#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;
        int sign;
        vecint vec;
        size_t nsize, dsize;
    };
    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 getDpsize(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;

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;
    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 = 3;
#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(),
              getDpsize(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::getDpsize(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 t = *this, r = "0";
    if (num.sign != 0)
    {
        attr &rum = t.num;
        for (int &k : rum.vec)
        {
            k *= i;
        }
        Carry(rum.vec);
        r = ClearStrZero(Vec2Str(rum.vec, rum.sign, rum.dsize));
    }
    return r;
}
/***********************************************************************/
//数字属性
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;
}
void lnum::setprecision(const size_t i)
{
    lnum::precision = i;
}
ostream &operator<<(ostream &os, const lnum &l)
{
    os << l.num.str;
    return os;
}
istream &operator>>(istream &is, lnum &l)
{ 
    string inputstr;
    (is >> inputstr).get();
    l = inputstr;
    return is;
}
=======================================================================
#include "E:\Users\admin\Documents\VScode\Code\My Class\largenum\lnum.cpp"
int main(int argc, char const *argv[])
{
    lnum a = "-5.000009", b = "6000";
    std::cout << (a + b) << std::endl;
    (a + b).showinfo();
    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-tmgi4wns.nfx --stdout=Microsoft-MIEngine-Out-sz504ytr.rqz --stderr=Microsoft-MIEngine-Error-ni2x4gi1.12t --pid=Microsoft-MIEngine-Pid-mtm4v2ay.ggn --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi
5994.999991
正/负/零: 1
原始字符: 5994.999991
数字元素: 5 9 9 4 9 9 9 9 9 1
数字长度: 10
小数位数: 6


E:\Users\admin\Documents\VScode\Code>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 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>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-5 17:38:20 | 显示全部楼层

优化代码

本帖最后由 bin554385863 于 2020-1-5 18:06 编辑

lnum.h
/*
(1)原始数字字符串->清除无效的零->转换数组,提取信息(小数位数,整数位数,是否为零);
(2)整体对齐->比较大小,设计加/减法;
(3)小数位对齐->设计数组乘整数->设计数组乘数组->实现对象乘法;
(补充)实现满十进一,退一借十;
*/
#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;

public:
    lnum(const char *cstr = "0") : data(getInfo(cstr)){}
    lnum(const string &s):data(getInfo(s)){}
    void showinfo() const;
    //(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;
    //(F)<<
    friend ostream &operator<<(ostream &os, const lnum &l);
};
#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;
    if (s[0] != '-'&&!isdigit(s[0]))
    {
        f = false;
    }
    else
    {
        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 = clearInvalidZero(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;
    }
}
//==========================================================================
//(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;
}
//(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) || (*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 == 0) > (tsgn == -1) ? 0 : -1;
        }
        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;
        string str = vecToStr(greater, sgn, dsz);
        r = str;
    }
    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;
}
//(F)<<
ostream &operator<<(ostream &os, const lnum &l)
{
    os << l.data.nstr;
    return os;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-5 20:08:33 | 显示全部楼层
本帖最后由 bin554385863 于 2020-1-5 20:23 编辑

继续优化

lnum.h
/*
(1)原始数字字符串->清除无效的零->转换数组,提取信息(小数位数,整数位数,是否为零);
(2)整体对齐->比较大小,设计加/减法;
(3)小数位对齐->设计数组乘整数->设计数组乘数组->实现对象乘法;
(补充)实现满十进一,退一借十;
*/
#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 outPut() 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;
    //(F)<<
    friend ostream &operator<<(ostream &os, const lnum &l);
    //(F)>>
    friend istream &operator>>(istream &is, lnum &l);
};
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 = clearInvalidZero(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::outPut() 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 str;
}
//==========================================================================
//(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) || (*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;
        //string str = vecToStr(greater, sgn, dsz);
        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;
}
//(F)<<
ostream &operator<<(ostream &os, const lnum &l)
{
    os << l.outPut();
    return os;
}
//(F)>>
istream &operator>>(istream &is, lnum &l)
{
    string str;
    (std::cin >> str).get();
    l = str;
    return is;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-5 20:25:49 | 显示全部楼层
添加减法
const lnum operator-(const lnum &l) const;
const lnum lnum::operator-(const lnum &l) const
{
    return *this + (-l);
}

test.cpp
#include "E:\Users\admin\Documents\VScode\Code\My Class\lnum\lnum.cpp"
#include <ctime>
#include <cmath>
int main(int argc, char const *argv[])
{
    lnum a = "1", b;
    while ((a + b) != "0")
    {
        std::cin >> a >> b;
        std::cout << "a - b = " << (a - b) << "\n"
                  << "a + b = " << (a + b) << "\n==========================\n";
    }
    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-x4qpcw2n.sc2 --stdout=Microsoft-MIEngine-Out-pmiyg52x.pko --stderr=Microsoft-MIEngine-Error-ycnrwdt4.obr --pid=Microsoft-MIEngine-Pid-5gacmwbw.dbc --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi
123
654
a - b = -531
a + b = 777
==========================
999
999
a - b = 0
a + b = 1998
==========================
987654321
123456789
a - b = 864197532
a + b = 1111111110
==========================
-99
999
a - b = -1098
a + b = 900
==========================
999
-99
a - b = 1098
a + b = 900
==========================
-5555
-9999
a - b = 4444
a + b = -15554
==========================
2
0.123654
a - b = 1.876346
a + b = 2.123654
==========================
0.123456789
0.000000005
a - b = 0.123456
a + b = 0.123456
==========================
0.0006
0.0005
a - b = 0.0001
a + b = 0.0011
==========================
-0.005
0.00004
a - b = -0.00504
a + b = -0.00496
==========================
1
-0.00005
a - b = 1.00005
a + b = 0.99995
==========================
-99999
-0.0006
a - b = -99998.9994
a + b = -99999.0006
==========================
-987
987
a - b = -1974
a + b = 0
==========================


E:\Users\admin\Documents\VScode\Code>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-5 23:00:24 | 显示全部楼层
bin554385863 发表于 2020-1-5 20:25
添加减法
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);

//(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";
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-6 03:21:05 | 显示全部楼层
本帖最后由 bin554385863 于 2020-1-6 04:30 编辑

已经实现
数字字符串加减乘三种运算和五种比较运算,


lnum.cpp
/*
(1)原始数字字符串->清除无效的零->转换数组,提取信息(小数位数,整数位数,是否为零);
(2)整体对齐->比较大小,设计加/减法;
(3)小数位对齐->设计数组乘整数->设计数组乘数组->实现对象乘法;
(补充)实现满十进一,退一借十;
*/
#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;
    //(F)<<
    friend ostream &operator<<(ostream &os, const lnum &l);
    //(F)>>
    friend istream &operator>>(istream &is, lnum &l);
};
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) || (*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;
        //string str = vecToStr(greater, sgn, dsz);
        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;
}
//(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;
}

===========================================
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-5 05:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表