Advertisement
zhangsongcui

LINP V2.0

Aug 17th, 2012
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <vector>
  4. #include <complex>
  5. #include <functional>
  6. #include <stdexcept>
  7.  
  8. using namespace std;
  9. class LINP
  10. {
  11. public:
  12.     // Index => Coeff
  13.     typedef vector<double> cont_type;
  14.  
  15. public:
  16.     LINP(): cont() {}
  17.     LINP(double rhs): cont(1) {
  18.         cont[0] = rhs;
  19.     }
  20.  
  21.     LINP operator [](size_t rhs) const {
  22.         if (rhs == 0)
  23.             return LINP(1);
  24.         LINP tmp(*this);
  25.         while (--rhs != 0)
  26.             tmp *= *this;
  27.         return tmp;
  28.     }
  29.  
  30.     LINP& operator *=(double rhs) {
  31.         for (auto& v : cont)
  32.             v *= rhs;
  33.         return *this;
  34.     }
  35.     LINP operator *(double rhs) const {
  36.         LINP tmp(*this);
  37.         tmp *= rhs;
  38.         return tmp;
  39.     }
  40.  
  41.     LINP& operator *=(const LINP& rhs) {
  42.         if (rhs.cont.empty()) {
  43.             cont.clear();
  44.             return *this;
  45.         } else if (this == &rhs) {
  46.             return *this *= LINP(*this);
  47.         }
  48.         shrinkToFit();
  49.         cont.reserve(rhs.maxIndex() + maxIndex());
  50.  
  51.         LINP tmp(*this);
  52.         cont.clear();
  53.         for (auto& v : rhs.cont) {
  54.             if (v != 0)
  55.                 *this += tmp * v;
  56.             tmp.cont.insert(tmp.cont.begin(), 0);
  57.         }
  58.         return *this;
  59.     }
  60.     LINP operator *(const LINP& rhs) const {
  61.         LINP tmp(*this);
  62.         tmp *= rhs;
  63.         return tmp;
  64.     }
  65.  
  66.     LINP& operator +=(const LINP& rhs) {
  67.         // Seems safe when this == &rhs
  68.         if (cont.size() < rhs.cont.size())
  69.             cont.resize(rhs.cont.size());
  70.         auto it = cont.begin();
  71.         for (auto& v : rhs.cont)
  72.             *it++ += v;
  73.         return *this;
  74.     }
  75.     LINP operator +(const LINP& rhs) const {
  76.         LINP tmp(*this);
  77.         tmp += rhs;
  78.         return tmp;
  79.     }
  80.  
  81.     LINP& operator -=(const LINP& rhs) {
  82.         if (this == &rhs) {
  83.             cont.clear();
  84.         } else {
  85.             if (cont.size() < rhs.cont.size())
  86.                 cont.resize(rhs.cont.size());
  87.             auto it = cont.begin();
  88.             for (auto& v : rhs.cont)
  89.                 *it++ -= v;
  90.         }
  91.         return *this;
  92.     }
  93.     LINP operator -(const LINP& rhs) const {
  94.         LINP tmp(*this);
  95.         tmp -= rhs;
  96.         return tmp;
  97.     }
  98.     LINP operator -() const {
  99.         LINP tmp(*this);
  100.         for (auto& v : tmp.cont)
  101.             v = -v;
  102.         return tmp;
  103.     }
  104.  
  105.     friend ostream& operator <<(ostream& os, const LINP& rhs) {
  106.         if (rhs.cont.size() > 1) {
  107.             for (cont_type::size_type idx = rhs.cont.size() - 1; idx != 0; --idx) {
  108.                 double coeff = rhs.cont[idx];
  109.                 if (coeff == 0)
  110.                     continue;
  111.                 if (coeff < 0) {
  112.                     os << "-";
  113.                     if (coeff != -1)
  114.                         os << -coeff;
  115.                 } else {
  116.                     os << "+";
  117.                     if (coeff != 1)
  118.                         os << coeff;
  119.                 }
  120.                 os << 'X';
  121.                 if (idx != 1)
  122.                     os << '[' << idx << ']';
  123.             }
  124.         }
  125.         if (!rhs.cont.empty()) {
  126.             double coeff = rhs.cont.front();
  127.             if (coeff != 0) {
  128.                 if (coeff > 0)
  129.                     os << '+';
  130.                 os << coeff;
  131.             }
  132.         } else {
  133.             os << '0';
  134.         }
  135.         return os;
  136.     }
  137.  
  138.     void shrinkToFit() {
  139.         cont.resize(maxIndex() + 1);
  140.     }
  141.  
  142.     size_t maxIndex() const {
  143.         return distance(find_if(cont.rbegin(), cont.rend(), [] (double coeff) {
  144.             return coeff != 0;
  145.         }), cont.rend()) - 1;
  146.     }
  147.  
  148.     double getCoeffOfIndex(size_t Index) const {
  149.         return Index > maxIndex() ? cont[Index] : 0;
  150.     }
  151.  
  152.     vector<complex<double> > solve() const throw(invalid_argument)  {
  153.         size_t maxIdx = maxIndex();
  154.         if (maxIdx > 2)
  155.             throw invalid_argument("只支持一次和二次多项式");
  156.         vector<complex<double> > result;
  157.         result.reserve(maxIdx);
  158.         if (maxIdx == 1) {
  159.             result.push_back(-cont[0] / cont[1]);
  160.         } else {
  161.             complex<double> delta=pow(cont[1], 2) - 4 * cont[2] * cont[0];
  162.             result.push_back((+sqrt(delta) - cont[1]) / (2 * cont[2]));
  163.             result.push_back((-sqrt(delta) - cont[1]) / (2 * cont[2]));
  164.         }
  165.         return result;
  166.     }
  167.  
  168.     static LINP getX() {
  169.         LINP x;
  170.         x.cont.resize(2);
  171.         x.cont.back() = 1;
  172.         return x;
  173.     }
  174.  
  175. private:
  176.     cont_type cont;
  177. };
  178.  
  179. int main()
  180. {
  181.     const static LINP X = LINP::getX();
  182.     LINP expression = (X + 1)[3];
  183.     cout << expression;
  184.  
  185.     LINP linp=X-(X*0.5+1)-1;
  186.     cout << linp << " = 0" << endl;
  187.     cout << "X = " << linp.solve().front().real() << endl << endl;
  188.  
  189.     LINP linp2=X[2] + X*2 + 1;
  190.     cout << linp2 << " = 0" << endl;
  191.     cout << "X1 = X2 = " << linp2.solve().front().real() << endl << endl;
  192.  
  193.     LINP linp3=X[2] + 1;
  194.     cout << linp3 << " = 0" << endl;
  195.     vector<complex<double> > result=linp3.solve();
  196.     cout << "x1 = " << result[0].real() << " + " << result[0].imag() << 'i' << endl
  197.          << "x2 = " << result[1].real() << " + " << result[1].imag() << 'i' << endl
  198.          << endl;
  199. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement