I Love Big Numbers!


My big integer class is finally finished. I have not tested it extensively yet. Anybody who is willing to find a tiny and clearly implemented big number class would find it worthy to have a try. Bug reports are always welcomed.

big_unsigned.hpp:
  1. /***************************************************************************
  2.  *   Copyright (C) 2008 by Liu Kaipeng                                     *
  3.  *   LiuKaipeng at gmail dot com                                           *
  4.  ***************************************************************************/
  5. #ifndef BIG_UNSIGNED_H
  6. #define BIG_UNSIGNED_H
  7. #include <algorithm>
  8. #include <fstream>
  9. #include <limits>
  10. #include <sstream>
  11. #include <vector>
  12. /*
  13.  * basic_big_unsigned - A implementation of big unsigned operations.
  14.  *
  15.  * This class is in fact a wrapper of the underlying container.
  16.  */
  17. template<typename Type, typename Container = std::vector<Type> >
  18. struct basic_big_unsigned
  19. {
  20.   typedef basic_big_unsigned self_type;
  21.   typedef Container container_type;
  22.   typedef typename container_type::value_type value_type;
  23.   typedef typename container_type::size_type size_type;
  24.   static int const repr_digits = std::numeric_limits<value_type>::digits;
  25.   static value_type const repr_base = 1 << (repr_digits / 2);
  26.   // Constructs.
  27.   basic_big_unsigned() {}
  28.  
  29.   basic_big_unsigned(value_type other) { 
  30.     if (other) repr_.push_back(other), progress(0); 
  31.   }
  32.   explicit basic_big_unsigned(container_type const& repr) : repr_(repr) {}
  33.   // Conversions.
  34.   value_type value() const {
  35.     value_type u = value_type();
  36.     for (size_type i = 0; i != repr_.size() && i != 2; ++i) 
  37.       u = u * repr_base + repr_[i];
  38.     return u;
  39.   }
  40.   // Representations.
  41.   container_type& repr() { return repr_; }
  42.   container_type const& repr() const { return repr_; }
  43.   bool is_zero() const { return repr_.empty(); }
  44.   // Operations.
  45.   self_type& operator+=(self_type const& other) {
  46.     if (repr_.size() < other.repr_.size())
  47.       repr_.resize(other.repr_.size());
  48.     size_type i = 0;
  49.     value_type carry = 0;
  50.     for (; i != other.repr_.size(); ++i)
  51.       if (overflow(repr_[i] += other.repr_[i] + carry))
  52.         repr_[i] -= repr_base, carry = 1;
  53.       else
  54.         carry = 0;
  55.     if (carry != 0)
  56.       if (i == repr_.size()) repr_.push_back(carry);
  57.       else repr_[i] += carry, progress(i);
  58.     return *this;
  59.   }
  60.   self_type& operator+=(value_type other) {
  61.     if (overflow(other))
  62.       return *this += self_type(other);
  63.     if (is_zero()) repr_.resize(1);
  64.     repr_[0] += other;
  65.     progress(0);
  66.     return *this;
  67.   }
  68.   self_type operator+(self_type const& other) const {
  69.     self_type tmp(*this); tmp += other; return tmp;
  70.   }
  71.   self_type operator+(value_type other) const {
  72.     self_type tmp(*this); tmp += other; return tmp;
  73.   }
  74.   self_type& operator-=(self_type const& other) {
  75.     size_type i = 0;
  76.     for (; i != other.repr_.size(); ++i)
  77.       if (underflow(repr_[i] -= other.repr_[i]))
  78.         --repr_[i+1], repr_[i] += repr_base;
  79.     degress(i);
  80.     return *this;
  81.   }
  82.   self_type& operator-=(value_type other) {
  83.     repr_[0] -= other;
  84.     degress(0);
  85.     return *this;
  86.   }
  87.   self_type operator-(self_type const& other) const {
  88.     self_type tmp(*this); return tmp -= other;
  89.   }
  90.   self_type operator-(value_type other) const {
  91.     self_type tmp(*this); return tmp -= other;
  92.   }
  93.   self_type& operator*=(self_type const& other) {
  94.     return *this = *this * other;
  95.   }
  96.   self_type& operator*=(value_type other) {
  97.     if (overflow(other))
  98.       return *this *= self_type(other);
  99.     value_type carry = 0;
  100.     for (size_type i = 0; i != repr_.size(); ++i) {
  101.       repr_[i] *= other;
  102.       repr_[i] += carry;
  103.       carry = repr_[i] / repr_base;
  104.       repr_[i] -= carry * repr_base;
  105.     }
  106.     if (carry != 0) repr_.push_back(carry);
  107.     return *this;
  108.   }
  109.   self_type operator*(self_type const& other) const {
  110.     self_type tmp;
  111.     if (!other.is_zero()) {
  112.       tmp.repr_.resize(repr_.size() + other.repr_.size());
  113.       for (size_t i = 0; i != repr_.size(); ++i)
  114.         for (size_t j = 0; j != other.repr_.size(); ++j)
  115.           if (overflow(tmp.repr_[i+j] += repr_[i] * other.repr_[j])) {
  116.             tmp.repr_[i+j+1] += tmp.repr_[i+j] / repr_base;
  117.             tmp.repr_[i+j] %= repr_base;
  118.           }
  119.       tmp.strip();
  120.     }
  121.     return tmp;
  122.   }
  123.   self_type operator*(value_type other) const {
  124.     self_type tmp(*this); return tmp *= other;
  125.   }
  126.   self_type& operator/=(self_type const& other) {
  127.     return *this = *this / other;
  128.   }
  129.   self_type& operator/=(value_type other) {
  130.     value_type rem;
  131.     div_with_rem(other, rem);
  132.     return *this;
  133.   }
  134.   self_type operator/(self_type const& other) const {
  135.     self_type tmp(*this);
  136.     tmp = tmp.div_to_rem(other);
  137.     return tmp;
  138.   }
  139.   self_type operator/(value_type other) const {
  140.     self_type tmp(*this); return tmp /= other;
  141.   }
  142.   self_type& operator%=(self_type const& other) {
  143.     div_to_rem(other);
  144.     return *this;
  145.   }
  146.   self_type& operator%=(value_type other) {
  147.     div_to_rem(self_type(other));
  148.     return *this;
  149.   }
  150.   self_type operator%(self_type const& other) const {
  151.     self_type tmp(*this); return tmp %= other;
  152.   }
  153.   value_type operator%(value_type other) const {
  154.     value_type rem;
  155.     self_type tmp(*this);
  156.     tmp.div_with_rem(other, rem);
  157.     return rem;
  158.   }
  159.   self_type& operator++() { return *this += 1; }
  160.   self_type operator++(int) { self_type tmp(*this); return tmp += 1; }
  161.   self_type& operator--() { return *this -= 1; }
  162.   self_type operator--(int) { self_type tmp(*this); return tmp -= 1; }
  163.   // Modular operations.
  164.   self_type div_to_rem(self_type const& other) {
  165.     self_type tmp;
  166.     if (!is_zero() && repr_.size() >= other.repr_.size()) {
  167.       tmp.repr_.resize(repr_.size() - other.repr_.size() + 1);
  168.       for (size_type i = tmp.repr_.size(); i != 0; --i) {
  169.         value_type high = repr_base - 1, low = 0,
  170.           mul = (high + low + 1) >> 1;
  171.         for (; high > low; mul = (high + low + 1) >> 1)
  172.           if (less_mul_shift(other, mul, i-1)) high = mul - 1;
  173.           else low = mul;
  174.         sub_mul_shift(other, mul, i-1);
  175.         tmp.repr_[i-1] = mul;
  176.       }
  177.       tmp.degress(tmp.repr_.size());
  178.     }
  179.     return tmp;
  180.   }
  181.   void div_with_rem(value_type other, value_type& rem) {
  182.     rem = 0;
  183.     for (size_type i = repr_.size(); i != 0; --i) {
  184.       rem = rem * repr_base + repr_[i-1];
  185.       repr_[i-1] = rem / other;
  186.       rem -= repr_[i-1] * other;
  187.     }
  188.     strip();
  189.   }
  190. private:
  191.   static bool overflow(value_type u) { return u >= repr_base; }
  192.   static bool underflow(value_type u) { return u - repr_base < -repr_base; }
  193.   void strip() { for (; !is_zero() && repr_.back() == 0; ) repr_.pop_back(); }
  194.   void progress(size_type pos) {
  195.     value_type carry = 0;
  196.     for (; pos != repr_.size() && overflow(repr_[pos] += carry); ++pos) {
  197.       carry = repr_[pos] / repr_base;
  198.       repr_[pos] -= carry * repr_base;
  199.     }
  200.     if (pos == repr_.size() && carry != 0) repr_.push_back(carry);
  201.   }
  202.   void degress(size_type pos) {
  203.     value_type borrow = 0;
  204.     for (; pos != repr_.size() && underflow(repr_[pos] -= borrow); ++pos) {
  205.       borrow = (repr_base - 1 - repr_[pos]) / repr_base;
  206.       repr_[pos] += borrow * repr_base;
  207.     }
  208.     if (pos == repr_.size() && borrow != 0) repr_.clear();
  209.     strip();
  210.   }
  211.   bool less_mul_shift(self_type const& other, value_type mul, size_type shift) 
  212.     const {
  213.     if (repr_.size() < other.repr_.size() + shift && mul)
  214.       return true;
  215.     value_type rem = 0, pro = 0;
  216.     for (size_type i = repr_.size(), j = i - shift; i != shift; --i, --j) {
  217.       rem = rem * repr_base + repr_[i-1];
  218.       pro = other.repr_.size() < j ? 0 : other.repr_[j-1] * mul;
  219.       if (rem < pro) return true;
  220.       if ((rem -= pro) >= mul) return false;
  221.     }
  222.     return false;
  223.   }
  224.   void sub_mul_shift(self_type const& other, value_type mul, size_type shift) {
  225.     size_type i = shift;
  226.     for (; i != other.repr_.size() + shift; ++i) {
  227.       if (underflow(repr_[i] -= other.repr_[i-shift] * mul)) {
  228.         value_type borrow = (repr_base - 1 - repr_[i]) / repr_base;
  229.         repr_[i+1] -= borrow;
  230.         repr_[i] += borrow * repr_base;
  231.       }
  232.     }
  233.     degress(i);
  234.   }
  235. private:
  236.   container_type repr_;
  237. };
  238. // Comparisons of basic_big_unsigned.
  239. template<typename Type, typename Container>
  240. inline bool operator==(basic_big_unsigned<Type, Container> const& x,
  241.                        basic_big_unsigned<Type, Container> const& y) {
  242.   return x.repr() == y.repr();
  243. }
  244. template<typename Type, typename Container>
  245. inline bool operator!=(basic_big_unsigned<Type, Container> const& x,
  246.                        basic_big_unsigned<Type, Container> const& y) {
  247.   return !(x == y);
  248. }
  249. template<typename Type, typename Container>
  250. inline bool operator<(basic_big_unsigned<Type, Container> const& x,
  251.                       basic_big_unsigned<Type, Container> const& y) {
  252.   if (x.repr().size() != y.repr().size())
  253.     return x.repr().size() < y.repr().size();
  254.   else
  255.     return std::lexicographical_compare(x.repr().rbegin(), x.repr().rend(),
  256.                                         y.repr().rbegin(), y.repr().rend());
  257. }
  258. template<typename Type, typename Container>
  259. inline bool operator>(basic_big_unsigned<Type, Container> const& x,
  260.                       basic_big_unsigned<Type, Container> const& y) {
  261.   return y < x;
  262. }
  263. template<typename Type, typename Container>
  264. inline bool operator<=(basic_big_unsigned<Type, Container> const& x,
  265.                        basic_big_unsigned<Type, Container> const& y) {
  266.   return !(y < x);
  267. }
  268. template<typename Type, typename Container>
  269. inline bool operator>=(basic_big_unsigned<Type, Container> const& x,
  270.                        basic_big_unsigned<Type, Container> const& y) {
  271.   return !(x < y);
  272. }
  273. // Input and output of basic_big_unsigned.
  274. template<typename Type, typename Container>
  275. std::istream& operator>>(std::istream& is,
  276.                          basic_big_unsigned<Type, Container>& u) {
  277.   typedef basic_big_unsigned<Type, Container> big_unsigned_type;
  278.   typedef typename big_unsigned_type::value_type value_type;
  279.   value_type base = big_unsigned_type::repr_base;
  280.   std::size_t digits = 4;
  281.   std::ios_base::fmtflags flags = is.flags();
  282.   if (flags & std::ios_base::dec) base = 10000;
  283.   if (flags & std::ios_base::oct) digits = 5;
  284.   u.repr().clear();
  285.   value_type val;
  286.   std::stringstream ss;
  287.   ss.flags(is.flags());
  288.   for (char buf[5]; is.read(buf, digits) && ss.write(buf, is.gcount()); )
  289.     ss >> val, u *= base, u += val;
  290.   return is;
  291. }
  292. template<typename Type, typename Container>
  293. std::ostream& operator<<(std::ostream& os,
  294.                          basic_big_unsigned<Type, Container> const& u) {
  295.   typedef basic_big_unsigned<Type, Container> big_unsigned_type;
  296.   typedef typename big_unsigned_type::value_type value_type;
  297.   if (u.is_zero()) return os << "0";
  298.   value_type base = big_unsigned_type::repr_base;
  299.   std::size_t digits = 4;
  300.   std::ios_base::fmtflags flags = os.flags();
  301.   if (flags & std::ios_base::dec) base = 10000;
  302.   if (flags & std::ios_base::oct) digits = 5;
  303.   value_type val;
  304.   std::vector<value_type> vals;
  305.   for (big_unsigned_type tmp(u); !tmp.is_zero(); vals.push_back(val))
  306.     tmp.div_with_rem(base, val);
  307.   os << vals.back();
  308.   if (vals.size() > 1) {
  309.     char f = os.fill('0');
  310.     for (std::size_t i = vals.size() - 1; i != 0; --i)
  311.       os.width(digits), os << vals[i-1];
  312.     os.fill(f);
  313.   }
  314.   return os;
  315. }
  316. typedef basic_big_unsigned<unsigned> big_unsigned;
  317. #endif /* BIG_UNSIGNED_H */

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章