V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
BRS5672023
V2EX  ›  C++

C++ 新手问下有没有办法链式定义一个类

  •  
  •   BRS5672023 · 66 天前 · 1615 次点击
    这是一个创建于 66 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如说我先定义一个单项式类为这种形式:

    a * pow(p, n) * pow(q, m)
    

    其中 a, m, n 都是整数,p 和 q 是两个字符,然后现在我想定义操作一个更复杂的类,就是一般所说的多项式,但是它要满足我添加一个单项式进来之后仍然还是一个多项式的要求。。

    第 1 条附言  ·  66 天前

    用了下 chatgpt 对照着写了下大概完成了(手法很原始,抱歉我实在没啥基础)

    #include <iostream>
    using namespace std;
    
    #include <string>
    #include <vector>
    
    // We define first the monomial class to be of the form a * pow(p, n) * power(q, m). We also fix the variables p, q here.
    class Mono {
        public:
            int coefficient;
            int power1;
            int power2;
    
            Mono(int a, int n = 0, int m = 0) : coefficient(a), power1(n), power2(m) {}
    };
    
    class Poly {
        friend ostream & operator<<(ostream & os, const Poly & poly);
        private:
            vector<Mono> terms;
    
        public:
            Poly & addTerm(const Mono & term) {
                terms.push_back(term);
                return * this;
            }
    };
    
    ostream & operator<<(ostream & os, const Poly & poly) {
        for (size_t i = 0; i < poly.terms.size(); i++) {
            const auto & term = poly.terms[i];
            if (term.coefficient != 0) {
                if (term.power1 == 0 && term.power2 == 0) {
                    os << term.coefficient;
                }
                else if (term.power1 == 0) {
                    os << term.coefficient << " * pow(q, " << term.power2 << ")";
                }
                else if (term.power2 == 0) {
                    os << term.coefficient << " * pow(p, " << term.power1 << ")";
                }
                else {
                    os << term.coefficient << " * pow(p, " << term.power1 << ") * " << "pow(q, " << term.power2 << ")";
                }
                if (i < poly.terms.size() - 1) {
                    os << " + ";
                }
            }
        }
        return os;
    }
    
    int main() {
        Poly poly;
        poly.addTerm(Mono(3)).addTerm(Mono(0,1)).addTerm(Mono(1,1)).addTerm(Mono(1,0,1)).addTerm(Mono(2,2,2));
    
        cout << "Polynomial:\n" << poly << endl;
    
        return 0;
    }
    

    输出结果是

    Polynomial:
    3 * pow(p, 2) * pow(q, 1) + 5 * pow(p, 2) * pow(q, 1)
    
    第 2 条附言  ·  66 天前

    上面 append 里的输出结果复制错了,应该是

    Polynomial:
    3 + 1 * pow(p, 1) + 1 * pow(q, 1) + 2 * pow(p, 2) * pow(q, 2)
    
    9 条回复    2024-10-22 15:54:02 +08:00
    jones2000
        1
    jones2000  
       66 天前
    不就是一个四则运算, 直接字符解析下, 不完是了, 计算机本科“编译原理”就有。 压栈出栈。
    c0xt30a
        2
    c0xt30a  
       66 天前
    你可能需要模版表达式跟操作符重载这两个特性(手法)。前者不如后者常见,你搜索下 C++ expression templates
    molika
        3
    molika  
       66 天前
    写个逆波兰表达式就完事了.
    ipwx
        4
    ipwx  
       66 天前   ❤️ 1
    楼主要不要试试怎么能让你的 C++ 程序支持:

    auto p = Symbol("p");
    auto q = Symbol("q");

    auto expression = 3 * pow(p, 2) * pow(q, 1) + 5 * pow(p, 2) * pow(q, 1);
    std::cout << expression << std::endl;
    BRS5672023
        5
    BRS5672023  
    OP
       65 天前
    @ipwx 我试了一下,大概是下面的形式
    ```
    #include <iostream>
    using namespace std;

    #include <string>
    #include <vector>

    class Mono {
    public:
    int coefficient;
    char variable1;
    int power1;
    char variable2;
    int power2;

    Mono(int a, char p, int n = 0, char q = '1', int m = 0) : coefficient(a), variable1(p), power1(n), variable2(q), power2(m) {}

    bool isSameTerm(const Mono & other) {
    return(variable1 == other.variable1 && power1 == other.power1 && variable2 == other.variable2 && power2 == other.power2);
    }

    };

    Mono operator * (int coef, const Mono & mono) {
    return Mono(coef * mono.coefficient, mono.variable1, mono.power1, mono.variable2, mono.power2);
    }

    Mono operator * (const Mono & lhs, const Mono & rhs) {
    if (lhs.variable2 == '1' && rhs.variable2 == '1') {
    return Mono(lhs.coefficient * rhs.coefficient, lhs.variable1, lhs.power1, rhs.variable1, rhs.power1);
    }
    else if (lhs.variable1 == rhs.variable1 && lhs.variable2 == '1') {
    if (rhs.variable2 == '1') {
    return Mono(lhs.coefficient * rhs.coefficient, lhs.variable1, lhs.power1 + rhs.power1);
    }
    return Mono(lhs.coefficient * rhs.coefficient, lhs.variable1, lhs.power1 + rhs.power1, lhs.variable2, lhs.power2);
    }
    else if (lhs.variable1 == rhs.variable1 && rhs.variable2 == '1') { // We do not need consider the case when the second variable of lhs is '1', which was already contained in the last case.
    return Mono(lhs.coefficient * rhs.coefficient, lhs.variable1, lhs.power1 + rhs.power1, rhs.variable2, rhs.power2);
    }
    else if (lhs.variable1 == rhs.variable1 && lhs.variable2 == rhs.variable2) {
    return Mono(lhs.coefficient * rhs.coefficient, lhs.variable1, lhs.power1 + rhs.power1, lhs.variable2, lhs.power2 + rhs.power2);
    }
    else if (lhs.variable1 == rhs.variable2 && lhs.variable2 == rhs.variable1) {
    return Mono(lhs.coefficient * rhs.coefficient, lhs.variable1, lhs.power1 + rhs.power2, lhs.variable2, lhs.power2 + rhs.power1);
    }
    throw -1;
    }

    Mono pow(char variable, int power) {
    return Mono(1, variable, power);
    }

    class Poly {
    friend ostream & operator << (ostream & os, const Poly & poly);
    private:
    vector<Mono> terms;

    public:
    Poly & addTerm(const Mono & term) {
    terms.push_back(term);
    return * this;
    }

    Poly & operator + (const Mono & term) {
    addTerm(term);
    return * this;
    }

    void simplify() {
    for (size_t i = 0; i < terms.size(); i++) {
    for (size_t j = i + 1; j < terms.size(); j++) {
    if (terms[i].isSameTerm(terms[j])) {
    terms[i].coefficient = terms[i].coefficient + terms[j].coefficient;
    terms.erase(terms.begin() + j);
    j--;
    }
    }
    }
    }
    };

    ostream & operator << (ostream & os, const Poly & poly) {
    for (size_t i = 0; i < poly.terms.size(); i++) {
    const auto & term = poly.terms[i];
    if (term.coefficient != 0) {
    if (term.power1 == 0 && term.power2 == 0) {
    os << term.coefficient;
    }
    else if (term.power1 == 0) {
    os << term.coefficient << " * pow(" << term.variable2 << ", " << term.power2 << ")";
    }
    else if (term.power2 == 0) {
    os << term.coefficient << " * pow(" << term.variable1 << ", " << term.power1 << ")";
    }
    else {
    os << term.coefficient << " * pow(" << term.variable1 << ", " << term.power1 << ") * " << "pow(" << term.variable2 << ", " << term.power2 << ")";
    }
    if (i < poly.terms.size() - 1) {
    os << " + ";
    }
    }
    }
    return os;
    }

    int main() {
    try {
    Poly poly;
    poly = poly + (3 * pow('p', 2) * pow('q', 1)) + (5 * pow('p', 2) * pow('q', 1)) + (2 * pow('p', 1) * pow('q', 1));
    cout << "Polynomial before simplification:\n" << poly << endl;

    poly.simplify();
    cout << "Polynomial after simplification:\n" << poly << endl;
    }

    catch(int err0) {
    cout << "You must input polynomials of two variables with aligned variables for multiplication!" << endl;
    cout << "Error number: " << err0 << endl;
    }
    return 0;
    }
    ```
    问题是我这样写就必须这样定义一个多项式
    ```
    Poly poly;
    poly = poly + (3 * pow('p', 2) * pow('q', 1)) + (5 * pow('p', 2) * pow('q', 1)) + (2 * pow('p', 1) * pow('q', 1));
    ```
    还有就是无法区分 pow(p, n) * pow(q, m) 和 pow(q, m) * pow(p, n) 这两种形式(除非我指定两个 char 的顺序);不过第二个问题就是我一开始想要的对于非交换的多项式的计算。。(然后我期待可以计算两个多项式的对易子,最后计算得到关于 p q 的对易子的一个多项式)
    BRS5672023
        6
    BRS5672023  
    OP
       65 天前
    上面的程序输出的结果是
    ```
    Polynomial before simplification:
    3 * pow(p, 2) * pow(q, 1) + 5 * pow(p, 2) * pow(q, 1) + 2 * pow(p, 1) * pow(q, 1)
    Polynomial after simplification:
    8 * pow(p, 2) * pow(q, 1) + 2 * pow(p, 1) * pow(q, 1)
    ```
    blacktail
        7
    blacktail  
       65 天前
    看最后的回复,这是要多项式化简?
    BRS5672023
        8
    BRS5672023  
    OP
       65 天前
    @blacktail 只是随便写了下化简的部分;重点也不是在化简的部分,但是当然希望我的计算结果能够输出一个简化过的形式。。

    另外程序写的还是有挺多问题的,包括甚至不能计算展开多项式的乘积。。
    ipwx
        9
    ipwx  
       65 天前
    @BRS5672023 把 Mono 再拆开成为最基本的形式比较好。那样的话自然可以区分 p * q 或者 q * p 了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5259 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 09:25 · PVG 17:25 · LAX 01:25 · JFK 04:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.