プログラミング雑感  新JavaScript入門  JavaScript,Neo-Generation  掲示板  表紙
1. 多項式クラス(1)  3. 多項式クラス(3) 
プログラミング雑感
Written 7/8/01
2. 多項式クラス(2)
今までは簡単ですが、こっからが大変です。
さて、ちゃんとこのページを書き終えることができるのでしょうか。
コンストラクタ(1)
デフォルトコンストラクタはなんもしなくてもいいでしょう。
あと、簡単に書けるコンストラクタとしては、単項で1次のもの、
    Polynomial::Polynomial(string& a) {
        Term    t;
        t.insert(make_pair(a, 1));
        insert(make_pair(t, 1));
    }
 
と、何次でもいいもの、
    Polynomial::Polynomial(string& a, int b) {
        Term    t;
        if(b == 0)
            return;
        t.insert(make_pair(a, b));
        insert(make_pair(t, 1));
    }
 
が書けますね。まとめるとデフォルト値を使って、
    Polynomial::Polynomial(string& a, int b = 1) {
        Term    t;
        if(b == 0)
            return;
        t.insert(make_pair(a, b));
        insert(make_pair(t, 1));
    }
 
あと、値も暗黙のうちに多項式に変換すると便利なので、
    Polynomial::Polynomial(double a) {
        Term    t;
        if(a != 0)
            insert(make_pair(t, a));
    }
 
も作っておきましょう。
あ、めんどいので、
    typedef map<string,int>    Term;
 
としました。
こういう感じに使います。
    Polynomial  f, g, h;
    f = 3 * Polynomial("x") * Polynomial("y");  //3 * x * y
    g = Polynomial("z", 3);                     //z ^ 3
    h = f + g;                                  //3 * x * y + z ^ 3
 
本当は、
    Polynomial  f("3 * x * y + z ^ 3");
 
という感じに使いたいのですが、難しいので後回しです。
出力
入力は難しいので、出力が先です。
出力は例えば、
    x2 + 3yz
 
という多項式があったら、
    x * x + 3 * y * z
 
としたいです。
というのは、これだとそのままプログラムのソースに使えるからです。
素直に項ごとに書き出していきましょう。 係数が負のときと±1のときと最初の項に注意です。
    ostream& operator <<(ostream& os, const Polynomial& a) {
        Polynomial::const_iterator  p;
        Term::const_iterator    q;
        for(p = a.begin(); p != a.end(); ++p) {
            bool    one = true;     //係数が±1か
            if(p == a.begin()) {
                if(p->second == -1)
                    os << "-";
                else if(p->second != 1) {
                    os << p->second;
                    one = false;
                }
            }
            else {
                if(p->second == -1)
                    os << " - ";
                else if(p->second == 1)
                    os << " + ";
                else if(p->second > 0) {
                    os << " + " << p->second;
                    one = false;
                }
                else {
                    os << " - " << -p->second;
                    one = false;
                }
            }
            for(q = p->first.begin(); q != p->first.end(); ++q) {
                for(int i = 0; i < p->first->second; i++) {
                    if(q == p->first.begin() && i == 0 && one)
                        os << p->first->first;
                    else
                        os << " * " << p->first->first;
                }
            }
        }
        return os;
    }
 
項を取り出す
多項式があったとして、例えばxの項でまとめたいときってやりますよね。
    x3 + y3 + z3 + x2y + y2z + z2x + xyz

                -> x3 + (y + z)x2 + (y2 + yz + z2)x + (y3 + z3)
 
こういうときのためにgetTermsメソッドを作っておきます。
    map<int,Polynomial> Polynomial::getTerms(const string& a) const {
        map<int,Polynomial> result;
        Polynomial::const_iterator  p;
        Term::const_iterator    q;
        for(p = this->begin(); p != this->end(); ++p) {
            Polynomial  poly;
            if((q = p->first.find(a)) != p->first.end()) {
                Term    t = p->first;
                t.erase(a);
                poly.insert(make_pair(t, p->second));
                result[q->second] += poly;
            }
            else {
                poly.insert(make_pair(p->first, p->second));
                result[0] += poly;
            }
        }
        return result;
    }
 
例えば、引数がxを表す多項式として、帰ってきた値をaとすると、 a[0]がxを含まない項、a[1]がxの項、a[2]がx2の項、、、となります。
先ほどの例だと、
    0 -> y3 + z3
    1 -> y2 + yz + z2
    2 -> y + z
    3 -> 1
 
となります。
以上により作成されたPolynomialクラスは次のヘッダファイルです。
    polynomial.h
 
次回はこれを使って当初の目的を達成します。
first, prev, next, exit