鱼C论坛

 找回密码
 立即注册
查看: 1398|回复: 13

[技术交流] C++自写类实现大数阶乘

[复制链接]
发表于 2020-1-6 03:25:51 | 显示全部楼层 |阅读模式

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

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

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


  1. #ifndef LNUM_H
  2. #define LNUM_H
  3. #include <iostream>
  4. #include <string>
  5. #include <vector>
  6. using std::istream;
  7. using std::ostream;
  8. using std::string;
  9. using std::vector;
  10. class lnum
  11. {
  12.     struct ndata
  13.     {
  14.         int sign;
  15.         string nstr;
  16.         vector<int> nvec;
  17.         size_t isize, dsize;
  18.     };
  19.     struct align
  20.     {
  21.         vector<int> first, second;
  22.     };
  23.    
  24. private:
  25.     static size_t pre;
  26.     ndata data;
  27.     //(0)判断是否含有小数点
  28.     const bool hasDecPoint(const string &s) const;
  29.     //(1)判断字符串是否有效
  30.     const bool isInvalidStr(const string &s) const;
  31.     //(2)判断字符串元素是否全为零
  32.     const bool isStrElemAllZero(const string &s) const;
  33.     //(3)清除无效的零
  34.     const string clearInvalidZero(const string &s) const;
  35.     //(4)转换数组
  36.     const vector<int> strToVec(const string &s) const;
  37.     //(-4)转换字符串
  38.     const string vecToStr(const vector<int> &vint, int sgn, size_t dsz) const;
  39.     //(5)提取信息
  40.     const ndata getInfo(const string &s) const;
  41.     //(6)小数位对齐
  42.     align dAlign(const lnum &l) const;
  43.     //(7)整体对齐
  44.     align wAlign(const lnum &l) const;
  45.     //(8)满十进一
  46.     void carry(vector<int> &v) const;
  47.     //(9)借一补十
  48.     void borrow(vector<int> &v) const;
  49.     //(10)输出设置
  50.     const string setPrint() const;
  51.     //(11)lnum*n
  52.     const lnum operator*(const int &n) const;

  53. public:
  54.     lnum(const char *cstr = "0") : data(getInfo(cstr))
  55.     {
  56.     }
  57.     lnum(const string &s):data(getInfo(s)){}
  58.     void showinfo() const;
  59.     static void setprecision(const size_t p);
  60.     //(1)>号
  61.     const bool operator>(const lnum &l) const;
  62.     //(2)==
  63.     const bool operator==(const lnum &l) const;
  64.     //(3)>=
  65.     const bool operator>=(const lnum &l) const;
  66.     //(4)<
  67.     const bool operator<(const lnum &l) const;
  68.     //(5)<=
  69.     const bool operator<=(const lnum &l) const;
  70.     //(5)!=
  71.     const bool operator!=(const lnum &l) const;
  72.     //(6)+
  73.     const lnum operator+(const lnum &l) const;
  74.     //(7)-反转正负
  75.     const lnum operator-() const;
  76.     //(7.5)-
  77.     const lnum operator-(const lnum &l) const;
  78.     //(8)+=
  79.     const lnum &operator+=(const lnum &l);
  80.     //(9)++
  81.     const lnum &operator++(const int i);
  82.     //(10)-=
  83.     const lnum &operator-=(const lnum &l);
  84.     //(11)--
  85.     const lnum &operator--(const int i);
  86.     //(12)lnum*lnum
  87.     const lnum operator*(const lnum &l) const;
  88.     //(10)*=
  89.     const lnum &operator*=(const lnum &l);
  90.     //(F)<<
  91.     friend ostream &operator<<(ostream &os, const lnum &l);
  92.     //(F)>>
  93.     friend istream &operator>>(istream &is, lnum &l);
  94.     ~lnum(){}
  95. };
  96. size_t lnum::pre = 6;
  97. #endif
复制代码


方法实现

lnum.cpp

  1. #include "E:\Users\admin\Documents\VScode\Code\My Class\lnum\lnum.h"
  2. //(0)判断是否含有小数点
  3. const bool lnum::hasDecPoint(const string &s) const
  4. {
  5.     return int(s.find('.')) > -1 ? true : false;
  6. }
  7. //(1)判断字符串是否有效
  8. const bool lnum::isInvalidStr(const string &s) const
  9. {
  10.     bool f = true;
  11.     string str = s;
  12.     if (str[0] == '-')
  13.     {
  14.         str.erase(0, 1);
  15.     }
  16.     if (!hasDecPoint(str))
  17.     {
  18.         for (char c : str)
  19.         {
  20.             if (!isdigit(c))
  21.             {
  22.                 f = false;
  23.                 break;
  24.             }
  25.         }
  26.     }
  27.     else
  28.     {
  29.         size_t dpinx = str.find('.');
  30.         f = (dpinx == 0) || (dpinx == (str.size() - 1)) || (dpinx != str.rfind('.')) ? false : true;
  31.         str.erase(dpinx, 1);
  32.         for (char c : str)
  33.         {
  34.             if (!isdigit(c))
  35.             {
  36.                 f = false;
  37.                 break;
  38.             }
  39.         }
  40.     }
  41.     return f;
  42. }
  43. //(2)判断字符串元素是否全为零
  44. const bool lnum::isStrElemAllZero(const string &s) const
  45. {
  46.     string str = s;
  47.     str[0] == '-' ? str.erase(0, 1) : str;
  48.     hasDecPoint(str) || false ? str.erase(str.find('.'), 1) : str;
  49.     return str == string(str.size(), '0') ? true : false;
  50. }
  51. //(3)清除无效的零
  52. const string lnum::clearInvalidZero(const string &s) const
  53. {
  54.     string str = s;
  55.     if (isInvalidStr(s))
  56.     {
  57.         size_t i = 0;
  58.         if (str[0] == '-')
  59.         {
  60.             str.erase(0, 1);
  61.         }
  62.         if (!hasDecPoint(s))
  63.         {
  64.             size_t sz = str.size();
  65.             while (i != sz)
  66.             {
  67.                 if (str[i] != '0')
  68.                 {
  69.                     break;
  70.                 }
  71.                 i++;
  72.             }
  73.             if (i == sz)
  74.             {
  75.                 str.erase(0, i - 1);
  76.             }
  77.             else if (i > 0)
  78.             {
  79.                 str.erase(0, i);
  80.             }
  81.         }
  82.         else
  83.         {
  84.             i = 0;
  85.             while (str[i] != '.')
  86.             {
  87.                 if (str[i] != '0')
  88.                 {
  89.                     break;
  90.                 }
  91.                 i++;
  92.             }
  93.             if (i == str.find('.'))
  94.             {
  95.                 str.erase(0, i - 1);
  96.             }
  97.             else if (i > 0)
  98.             {
  99.                 str.erase(0, i);
  100.             }
  101.             i = str.size() - 1;
  102.             while (str[i] != '.')
  103.             {
  104.                 if (str[i] != '0')
  105.                 {
  106.                     break;
  107.                 }
  108.                 i--;
  109.             }
  110.             if (i == str.find('.'))
  111.             {
  112.                 str.erase(i);
  113.             }
  114.             else if (i < str.size() - 1)
  115.             {
  116.                 str.erase(i + 1);
  117.             }
  118.         }
  119.     }
  120.     if (s[0] == '-' && str != "0")
  121.     {
  122.         str.insert(0, 1, '-');
  123.     }
  124. return str;
  125. }
  126. //(4)转换数组
  127. const vector<int> lnum::strToVec(const string &s) const
  128. {
  129.     vector<int> vint;
  130.     string str = s;
  131.     str[0] == '-' ? str.erase(0, 1) : str;
  132.     hasDecPoint(str) > false ? str.erase(str.find('.'), 1) : str;
  133.     for (char c : str)
  134.     {
  135.         vint.push_back(c - 48);
  136.     }
  137.     return vint;
  138. }
  139. //(-4)转换字符串
  140. const string lnum::vecToStr(const vector<int> &vint, int sgn, size_t dsz) const
  141. {
  142.     string str;
  143.     for (int i : vint)
  144.     {
  145.         str.push_back(i + 48);
  146.     }
  147.     if (str != "0")
  148.     {
  149.         dsz == 0 ? str : str.insert(str.size() - dsz, 1, '.');
  150.         sgn == -1 ? str.insert(0, 1, '-') : str;
  151.     }
  152.     return str;
  153. }
  154. //(5)提取信息
  155. const lnum::ndata lnum::getInfo(const string &s) const
  156. {
  157.     ndata ndt = {0, "0", {0}, 1, 0};
  158.     if (isInvalidStr(s))
  159.     {
  160.         ndt.nstr = s;
  161.         ndt.sign = ndt.nstr != "0" ? (ndt.nstr[0] == '-' ? -1 : 1) : 0;
  162.         ndt.dsize = hasDecPoint(ndt.nstr) || false ? ndt.nstr.size() - ndt.nstr.find('.') - 1 : 0;
  163.         ndt.nvec = strToVec(ndt.nstr);
  164.         ndt.isize = ndt.nvec.size() - ndt.dsize;
  165.     }
  166.     return ndt;
  167. }
  168. //(6)小数位对齐
  169. lnum::align lnum::dAlign(const lnum &l) const
  170. {
  171.     align agn;
  172.     vector<int> &f = agn.first, &s = agn.second;
  173.     f = data.nvec;
  174.     s = l.data.nvec;
  175.     const size_t &fds = data.dsize, &sds = l.data.dsize;
  176.     fds > sds ? s.insert(s.end(), fds - sds, 0) : f.insert(f.end(), sds - fds, 0);
  177.     return agn;
  178. }
  179. //(7)整体对齐
  180. lnum::align lnum::wAlign(const lnum &l) const
  181. {
  182.     align &&agn = this->dAlign(l);
  183.     vector<int> &f = agn.first, &s = agn.second;
  184.     const size_t &fws = data.isize, &sws = l.data.isize;
  185.     fws > sws ? s.insert(s.begin(), fws - sws, 0) : f.insert(f.begin(), sws - fws, 0);
  186.     return agn;
  187. }
  188. //(8)满十进一
  189. void lnum::carry(vector<int> &v) const
  190. {
  191.     v.insert(v.begin(), 1, 0);
  192.     const size_t s = v.size();
  193.     for (size_t i = s - 1; i != 0; i--)
  194.     {
  195.         int t = v[i];
  196.         v[i] = t % 10;
  197.         v[i - 1] += t / 10;
  198.     }
  199.     if (v[0] == 0)
  200.     {
  201.         v.erase(v.begin(), v.begin() + 1);
  202.     }
  203. }
  204. //(9)借一补十
  205. void lnum::borrow(vector<int> &v) const
  206. {
  207.     const size_t s = v.size();
  208.     for (size_t i = 1; i < s; i++)
  209.     {
  210.         v[i - 1] -= 1;
  211.         v[i] += 10;
  212.     }
  213. }
  214. //(10)输出设置
  215. const string lnum::setPrint() const
  216. {
  217.     const size_t &tds = data.dsize;
  218.     string str = data.nstr;
  219.     if (pre == 0)
  220.     {
  221.         if (tds != 0)
  222.         {
  223.             str.erase(str.find('.'));
  224.         }
  225.     }
  226.     else if (tds > pre)
  227.     {

  228.         str.erase(str.size() - (tds - pre));
  229.     }
  230.     return clearInvalidZero(str);
  231. }
  232. //(11)lnum*n
  233. const lnum lnum::operator*(const int &n) const
  234. {
  235.     vector<int> t = data.nvec;
  236.     for (int &i : t)
  237.     {
  238.         i *= n;
  239.     }
  240.     carry(t);
  241.     lnum r = vecToStr(t, data.sign, data.dsize);
  242.     return r;
  243. }
  244. //==========================================================================
  245. //(0)显示信息
  246. void lnum::showinfo() const
  247. {
  248.     std::cout << "正/负/零: " << data.sign << "\n"
  249.               << "原始数字: " << data.nstr << "\n"
  250.               << "数组元素: ";
  251.     for (int i : data.nvec)
  252.     {
  253.         std::cout << i << " ";
  254.     }
  255.     std::cout << std::endl;
  256.     std::cout << "整数位数: " << data.isize << "\n"
  257.               << "小数位数: " << data.dsize << std::endl;
  258. }
  259. void lnum::setprecision(const size_t p)
  260. {
  261.     pre = p;
  262. }
  263. //(1)>号
  264. const bool lnum::operator>(const lnum &l) const
  265. {
  266.     bool f = true;
  267.     const int &tsgn = data.sign, &lsgn = l.data.sign;
  268.     if (tsgn < lsgn)
  269.     {
  270.         f = false;
  271.     }
  272.     else if (tsgn == lsgn)
  273.     {
  274.         const align &agn = this->wAlign(l);
  275.         f = agn.first > agn.second;
  276.         if (tsgn == -1)
  277.         {
  278.             f = !f;
  279.         }
  280.     }
  281.     return f;
  282. }
  283. //(2)==
  284. const bool lnum::operator==(const lnum &l) const
  285. {
  286.     return (data.sign == l.data.sign) && (data.nvec == l.data.nvec);
  287. }
  288. //(3)>=
  289. const bool lnum::operator>=(const lnum &l) const
  290. {
  291.     return (*this > l) || (*this == l);
  292. }
  293. //(4)<
  294. const bool lnum::operator<(const lnum &l) const
  295. {
  296.     return !(*this >= l);
  297. }
  298. //(5)<=
  299. const bool lnum::operator<=(const lnum &l) const
  300. {
  301.     return !(*this > l);
  302. }
  303. //(5.5)!=
  304. const bool lnum::operator!=(const lnum &l) const
  305. {
  306.     return !(*this == l);
  307. }
  308. //(6)+
  309. const lnum lnum::operator+(const lnum &l) const
  310. {
  311.     lnum r;
  312.     if (*this != (-l))
  313.     {
  314.         align agn = this->wAlign(l);
  315.         vector<int> &fst = agn.first,
  316.                     &sec = agn.second,
  317.                     &greater = fst >= sec ? fst : sec,
  318.                     &less = sec <= fst ? sec : fst;
  319.         const int &tsgn = data.sign,
  320.                   &lsgn = l.data.sign;
  321.         const size_t &sz = fst.size();
  322.         for (size_t i = 0; i < sz; i++)
  323.         {
  324.             greater[i] += (lsgn * tsgn) * less[i];
  325.         }
  326.         int sgn = 1;
  327.         if (tsgn == lsgn)
  328.         {
  329.             sgn = tsgn;
  330.         }
  331.         else if (tsgn != lsgn)
  332.         {
  333.             sgn = ((greater == fst && tsgn < lsgn) || (less == fst && tsgn > lsgn)) || false ? -1 : sgn;
  334.         }
  335.         if (tsgn * lsgn == -1)
  336.         {
  337.             borrow(greater);
  338.         }
  339.         carry(greater);
  340.         size_t dsz = data.dsize >= l.data.dsize ? data.dsize : l.data.dsize;
  341.         r = vecToStr(greater, sgn, dsz);
  342.     }
  343.     return r;
  344. }

  345. //(7)-反转正负
  346. const lnum lnum::operator-() const
  347. {
  348.     lnum r = *this;
  349.     if (data.sign != 0)
  350.     {
  351.         r.data.sign = -data.sign;
  352.         r.data.nstr = vecToStr(data.nvec, -data.sign, data.dsize);
  353.     }
  354.     return r;
  355. }
  356. //(7.5)-
  357. const lnum lnum::operator-(const lnum &l) const
  358. {
  359.     return *this + (-l);
  360. }
  361. //(8)+=
  362. const lnum &lnum::operator+=(const lnum &l)
  363. {
  364.     return *this = *this + l;
  365. }
  366. //(9)++
  367. const lnum &lnum::operator++(const int i)
  368. {
  369.     return *this = *this + "1";
  370. }
  371. //(10)-=
  372. const lnum &lnum::operator-=(const lnum &l)
  373. {
  374.     return *this = *this + (-l);
  375. }
  376. //(11)--
  377. const lnum &lnum::operator--(const int i)
  378. {
  379.     return *this = *this + "-1";
  380. }
  381. //(12)lnum*lnum
  382. const lnum lnum::operator*(const lnum &l) const
  383. {
  384.     lnum r;
  385.     const int &tsgn = data.sign,
  386.               &lsgn = l.data.sign;
  387.     if (tsgn * lsgn == 0)
  388.     {
  389.         r = "0";
  390.     }
  391.     else
  392.     {
  393.         const vector<int> &tvec = data.nvec,
  394.                           &lvec = l.data.nvec;
  395.         const size_t &tsz = data.dsize,
  396.                      &lsz = l.data.dsize,
  397.                      &tvsz = tvec.size(),
  398.                      &lvsz = lvec.size(),
  399.                      &shrtsz = tvsz <= lvsz ? tvsz : lvsz;
  400.         lnum loong = tvsz >= lvsz ? *this : l;
  401.         const vector<int> &shrtv = lvsz <= tvsz ? lvec : tvec;
  402.         vector<int> &lovec = loong.data.nvec,
  403.                     &rvec = r.data.nvec;
  404.         for (size_t i = shrtsz - 1; i != -1; i--)
  405.         {
  406.             r += loong * shrtv[i];
  407.             if (i > 0)
  408.             {
  409.                 lovec.push_back(0);
  410.             }
  411.         }
  412.         r = vecToStr(rvec, tsgn * lsgn, tsz + lsz);
  413.     }
  414.     return r;
  415. }
  416. //(10)*=
  417. const lnum &lnum::operator*=(const lnum &l)
  418. {
  419.     return *this = *this * l;
  420. }
  421. //(F)<<
  422. ostream &operator<<(ostream &os, const lnum &l)
  423. {
  424.     os << l.setPrint();
  425.     return os;
  426. }
  427. //(F)>>
  428. istream &operator>>(istream &is, lnum &l)
  429. {
  430.     string str;
  431.     (std::cin >> str).get();
  432.     l = str;
  433.     return is;
  434. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-1-6 09:13:27 | 显示全部楼层
>>> import math
>>> math.factorial(200)
788657867364790503552363213932185062295135977687173263294742533244359449963403342920304284011984623904177212138919638830257642790242637105061926624952829931113462857270763317237396988943922445621451664240254033291864131227428294853277524242407573903240321257405579568660226031904170324062351700858796178922222789623703897374720000000000000000000000000000000000000000000000000
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-6 12:01:39 | 显示全部楼层
本帖最后由 bin554385863 于 2020-1-6 12:07 编辑
wp231957 发表于 2020-1-6 09:13
>>> import math
>>> math.factorial(200)
7886578673647905035523632139321850622951359776871732632947 ...


这里是C++,
不是Python OR go lang
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-6 12:19:33 | 显示全部楼层
至于除法我能想到的是模拟竖式计算...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-6 13:41:02 | 显示全部楼层
bin554385863 发表于 2020-1-6 12:19
至于除法我能想到的是模拟竖式计算...

减法可以用加法模拟,100 - 10 == 100 + (-10)
乘法可以用加法模拟,2 * 3 == 3 + 3 == 2 + 2 + 2
除法可以用乘法模拟
10 / 3

1 * 3 < 10
2 * 3 < 10
3 * 3 < 10
4 * 3 > 10

10 / 3 == 3

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

使用道具 举报

 楼主| 发表于 2020-1-6 13:42:51 | 显示全部楼层
人造人 发表于 2020-1-6 13:41
减法可以用加法模拟,100 - 10 == 100 + (-10)
乘法可以用加法模拟,2 * 3 == 3 + 3 == 2 + 2 + 2
除法 ...

加减乘我已经写出来了,就除法
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-6 13:47:46 | 显示全部楼层
我之前就是这样做的,只实现了加法操作
至于减法、乘法、除法、取余、乘方、开方 。。。
这些都是向下调用
例如,除法循环调用乘法函数,乘法函数循环调用加法函数

我的这个版本能够得到正确答案,就是非常慢,不骗你,因为都是向下调用,最终调用加法操作,真的非常慢,如果你没有好的思路,可以用这种方法试一试,^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-6 16:00:27 | 显示全部楼层
本帖最后由 bin554385863 于 2020-1-6 18:17 编辑
人造人 发表于 2020-1-6 13:47
我之前就是这样做的,只实现了加法操作
至于减法、乘法、除法、取余、乘方、开方 。。。
这些都是向下调 ...


我的想法是模拟手算竖式,最终也是递归个加法,
除不过就在末尾添0,添几个0就说明商是几位小数
比如
7
/
5

7-5 = 1-------2商的整数位是1

2/5除不过

2后面添0
同样的存储2/5的商的数组也填个0={0}

20-5(循环减) 4次正好为0

然后尾部插入数组中正好是{0,4}且小数位数是1
再加上第一个没有小数的数组{1}
相加既得结果数组{1,4}且小数位数为一,然后在转换成字符串输出

伪代码已经写出来了,正在考虑怎么写正式代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-6 16:04:40 | 显示全部楼层
bin554385863 发表于 2020-1-6 16:00
我的想法是模拟手算竖式,最终也是递归个加法,
除不过就在末尾添0,添几个0就说明商是几位小数
比如

也行,不过我还是认为我的方法好,起码好理解,只是运行没有效率罢了,^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-6 17:05:59 | 显示全部楼层
bin554385863 发表于 2020-1-6 16:00
我的想法是模拟手算竖式,最终也是递归个加法,
除不过就在末尾添0,添几个0就说明商是几位小数
比如

所以我之前说过的。。底层设计成2进制,在显示的时候再把二进制的数据转化为十进制显示。

这样除法就非常好算,直接减法模拟就好:


比如10011(19)除以101 (5):

首先除数左移,与被除数对齐:

10011
10100

然后能相减记1,不能相减记0,每次相减之后右移一位,直到位移量为0:

10011
10100

不能相减:记0

10011
101
能相减,记1,减去后剩余01001:
01001
00101
能相减,记1,减去后剩余00100:

位移量为0,结束
所以商为011(3),余数为00100(4)




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

使用道具 举报

 楼主| 发表于 2020-1-6 17:34:11 | 显示全部楼层
本帖最后由 bin554385863 于 2020-1-6 18:01 编辑
Croper 发表于 2020-1-6 17:05
所以我之前说过的。。底层设计成2进制,在显示的时候再把二进制的数据转化为十进制显示。

这样除法就 ...


直接使用二进制肯定不现实.
使用字符串模拟二进制的话,数字小还好.数组长度不算太长.但是数字如果太大的话十进制数组的长度可能要到上百个了更别说二进制了
比如100的阶乘!
  1. #include "E:\Users\admin\Documents\VScode\Code\My Class\lnum\lnum.cpp"
  2. #include <ctime>
  3. #include <cmath>
  4. lnum fact(const lnum &n)
  5. {
  6.     lnum fact = "1";
  7.     for (lnum i = "1"; i <= n; i++)
  8.     {
  9.         fact *= i;
  10.     }
  11.     return fact;
  12. }
  13. int main(int argc, char const *argv[])
  14. {
  15.     lnum a = "1";
  16.     // for (lnum i = "10"; i != "110"; i += "10")
  17.     // {
  18.     //     std::cout << i<<"! = "<<fact(i) << std::endl;
  19.     // }
  20.     fact("100").showinfo();
  21.     return 0;
  22. }
复制代码

  1. 正/负/零: 1
  2. 原始数字: 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
  3. 数组元素: 9 3 3 2 6 2 1 5 4 4 3 9 4 4 1 5 2 6 8 1 6 9 9 2 3 8 8 5 6 2 6 6 7 0 0 4 9 0 7 1 5 9 6 8 2 6 4 3 8 1 6 2 1 4 6 8 5 9 2 9 6 3 8 9 5 2 1 7 5 9 9 9 9 3 2 2 9 9 1 5 6 0 8 9 4 1 4 6 3 9 7 6 1 5 6 5 1
  4. 8 2 8 6 2 5 3 6 9 7 9 2 0 8 2 7 2 2 3 7 5 8 2 5 1 1 8 5 2 1 0 9 1 6 8 6 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  5. 整数位数: 158
  6. 小数位数: 0
复制代码


数组的元素越少,长度越短,计算起来肯定越快
所以我觉得可以用十六进制,但是进制转换有很蛋疼

十进制的好处是数组和字符串可以用 '0'进行一对一的转换,而不用考虑进制.你的这种方法给我提了另一个很好的思路
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-6 17:43:22 | 显示全部楼层
人造人 发表于 2020-1-6 16:04
也行,不过我还是认为我的方法好,起码好理解,只是运行没有效率罢了,^_^

我这种想法就是模拟小学除法竖式来的,加法也是.'

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

使用道具 举报

发表于 2020-1-6 17:45:41 | 显示全部楼层
bin554385863 发表于 2020-1-6 17:43
我这种想法就是模拟小学除法竖式来的,加法也是.'

我的加法函数用的算法就是竖式,^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-6 17:49:41 | 显示全部楼层
人造人 发表于 2020-1-6 17:45
我的加法函数用的算法就是竖式,^_^

本来考虑使用其他进制来着,嫌进制转换太麻烦,而且使用的是字符串和数组,还不如直接使用十进制了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-12 20:05

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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