如何修复我的 C++ 代码以计算复数?

How can I fix my C++ code to calculate Complex numbers?

我的 main.cpp.There 遇到了一些问题,有些地方我不知道必须编写什么才能使我的代码正常运行。我会在我的代码中写出问题所在。我在代码错误的地方写下问题词。有人知道我必须更改什么才能使我的代码正常工作吗? 我的代码是关于复数加法、减法、除法、乘法。

Komolex.h :

#pragma once
#include <iostream>

class NullDivision : public std::exception{};

class Complex{
    private:
        int n, d;
    public:
        Complex(int _n = 0, int _d = 1) : n(_n), d(_d)
        {
            if(d == 0)
            {
                throw NullDivision();
            }
        }

        Complex add(const Complex &b) const
        {
            Complex c(n + b.n , d + b.d);
            return c;
        }

        Complex sub(const Complex &b) const
        {
            Complex c(n - b.n , d - b.d);
            return c;
        }

        Complex mul(const Complex &b) const
        {
            Complex c(n * b.n - d * b.d ,n * b.d - d * b.n );
            return c;
        }

        Complex div(const Complex &b) const
        {
            if(b.n == 0 || b.d == 0)
            {
                throw NullDivision();
            }
            Complex c((n * d + d * b.d ) / (b.n * b.n + b.d * b.d ), (d * b.n + n * b.d )/(b.n * b.n + b.d * b.d));
            return c;
        }


        friend Complex operator+(const Complex &a, const Complex &b)
        {
            return Complex(a.n + b.n , a.d + b.d);
        }
        friend Complex operator-(const Complex &a, const Complex &b)
        {
            return Complex(a.n - b.n , a.d - b.d);
        }
        friend Complex operator*(const Complex &a, const Complex &b)
        {
            return Complex(a.n * b.n - a.d * b.d ,a.n * b.d - a.d * b.n );
        }
        friend Complex operator/(const Complex &a, const Complex &b)
        {
            if(b.n == 0)
            {
                throw NullDivision();
            }
            return Complex((a.n * a.d + a.d * b.d ) / (b.n * b.n + b.d * b.d ), (a.d * b.n + a.n * b.d )/(b.n * b.n + b.d * b.d));

        }
        friend std::ostream& operator<< (std::ostream& o, const Complex &a)
        {
            o << "(" << a.n << "/" << a.d << ")";
            return o;
        }
    
};

main.cpp :



#include <iostream>
#include "Komplex.h"
using namespace std;

int main()
{   bool fut = false;
    int szam;
    while (fut == false){
        cout << "1.Komplex számok összeadása" << endl;
        cout << "2.Komplex számok kivonása" << endl;
        cout << "3.Komplex számok szorzása"<< endl;
        cout << "4.Komplex számok osztása"<< endl;
        cout << "5.Kilépés"<< endl;
        cout << "Írjon be egy sorszámot!"<< endl;
        cin >> szam;

        if(szam == 5)
        {
            fut=true;
            break;
        }

    cout << endl;

    Complex n, d;
    cout << "Adja meg az első szám valós részét" << endl;
    cin >> n.a;  // Problem
    cout << "Adja meg az első szám képzetes részét" << endl;
    cin >> n.b; // Problem
    cout << "Adja meg a második szám valós részét" << endl;
    cin >> d.a; // Problem 
    cout << "Adja meg a második szám képzetes részét" << endl;
    cin >> d.b; // Problem

    Complex eredmeny;
    switch(szam){
        case 1:
            eredmeny = n + d;
            cout << "Az eredmény:" << eredmeny.a << + eredmeny.b << "i" << endl << endl;
            break;
        case 2:
            eredmeny = n - d;
            cout << "Az eredmény:" << eredmeny.a << + eredmeny.b << "i" << endl << endl;
            break;
        case 3:
            eredmeny = n * d;
            cout << "Az eredmény:" << eredmeny.a << + eredmeny.b << "i" << endl << endl;
            break;
        case 4:
        try {
            eredmeny = n / d;
            cout << "Az eredmény:" << eredmeny.a << + eredmeny.b << "i" << endl << endl;
        }
        catch(NullDivision e){std::cout << "NullDivision"<< std::endl;}

         std::cout << std::endl;
        break;
    
        }

    }
    return 0;
}

您的 Complex class 有两个成员变量,nd。您似乎试图将值放入 (non-existent) ab 成员变量中。

结局不会很好:-)

我建议,首先,使用让您的意图更清晰的变量名。例如,成员变量 nd 最好命名为 m_realm_imagnd 看起来它们应该代表分子和分母,但这与复数(a)没有任何关系

通过使用合适的变量名,阅读代码应该足以弄清楚发生了什么,并且您不太可能混淆 class 的成员变量和对象(另外 不应命名为 nd).


(a) 老实说,您似乎已经 re-tasked 一些代码,旨在将有理数用作复数。我基于变量命名和你的 Complex 构造函数具有的事实:

Complex(int _n = 0, int _d = 1) : n(_n), d(_d)
{
    if(d == 0)
    {
        throw NullDivision();
    }
}

我明白 没有 复数的虚部默认为 1 的原因,以及如果它为零则抛出 NullDivision 异常的原因。这基本上会从复数 class.

中删除整组实数

因此,使用更好的名称甚至 很重要,这样您就可以找出这些 re-tasked 错误的原因。


我将给你一个例子,说明专业开发人员如何编写这样的代码(尽管没有我通常有的大量评论)。

如果这是教育性的 class 作品,我不建议使用它,因为您可能会因剽窃而受到警告,但它应该作为如何去做的指南。

#include <iostream>

class ZeroDivision : public std::exception{};

struct Complex{
public:
    Complex(double real_bit = 0.0, double imag_bit = 0.0)
    : m_real(real_bit)
    , m_imag(imag_bit)
    {}

    friend Complex operator+(const Complex &me, const Complex &them) {
        return Complex(
            me.m_real + them.m_real,
            me.m_imag + them.m_imag);
    }

    friend Complex operator-(const Complex &me, const Complex &them) {
        return Complex(
            me.m_real - them.m_real,
            me.m_imag - them.m_imag);
    }

    friend Complex operator*(const Complex &me, const Complex &them) {
        return Complex(
            me.m_real * them.m_real - me.m_imag * them.m_imag,
            me.m_real * them.m_imag + me.m_imag * them.m_real);
    }

    friend Complex operator/(const Complex &me, const Complex &them) {
        if (them.m_real == 0 && them.m_imag == 0)
            throw ZeroDivision();

        return Complex(
            (me.m_real * them.m_real + me.m_imag * them.m_imag) / (them.m_real * them.m_real + them.m_imag * them.m_imag),
            (me.m_imag * them.m_real - me.m_real * them.m_imag) / (them.m_real * them.m_real + them.m_imag * them.m_imag));

    }

    friend std::ostream& operator<<(std::ostream& os, const Complex &var) {
        const char *sep = "+";
        if (var.m_imag < 0)
            sep = "";

        os << "(" << var.m_real << sep << var.m_imag << "i)";
        return os;
    }

private:
    double m_real, m_imag;
};

#include <iostream>
using namespace std;

int main() {
    Complex c1(19.65, 3.142);
    Complex c2(19.68, 2.718);
    Complex c3(2, 0);
    Complex c4(0, 2);
    Complex c5(0, 0);

    cout << c1 << " + " << c2 << " = " << (c1 + c2) << '\n';
    cout << c1 << " - " << c2 << " = " << (c1 - c2) << '\n';
    cout << c1 << " * " << c2 << " = " << (c1 * c2) << '\n';
    cout << c1 << " / " << c2 << " = " << (c1 / c2) << '\n';

    cout << c1 << " / " << c3 << " = " << (c1 / c3) << '\n';
    cout << c1 << " / " << c4 << " = " << (c1 / c4) << '\n';
 
   try {
        cout << c1 << " / " << c5 << " = " << (c1 / c5) << '\n';
        cout << "Did NOT successfully catch divide-by-zero\n";
    } catch (ZeroDivision &exc) {
        cout << "Successfully caught divide-by-zero\n";
    }

    return 0;
}

作为其中的一部分,我:

  • 摆脱了多余的东西。当您可以只使用 built-in 运算符时,addsub 等没有什么意义。
  • 使用构造函数(或运算符)创建了所有复数。您应该 而不是 尝试更改 classes 内部(私有)数据。如果必须这样做,请使用 setter 函数。
  • 对您的输出流代码进行了(非常轻微的)调整以改进格式。同样,这就是您应该用来输出对象的方法,而不是 试图直接访问私有数据。
  • 修复了 divide-by-zero 检测。只有当 实部和虚部都为零时才会发生这种情况,而如果 either 为零,则您将其提高。那意味着你永远无法将某物除以二,因为虚部为零,(2+0i).
  • 使部件成为浮点数而不是整数。如果你愿意,你可以改回它们,但浮点数在一般用途中可能更好 class.
  • 修正了乘法和除法公式。

为了解释最后一个要点,乘法 a * b 是,其中 ab 是复数,R 是实数部分,I虚数:

R = a.R * b.R - a.I * b.I  # correct.

I = a.R * b.I - a.I * b.R  # should be adding, not subtracting
              ^

对于除法 a / b,您有:

R = (a.R * a.I + a.I * b.I) / (b.R * b.R + b.I * b.I)
    (a.R * a.R + a.I * b.I) / (b.R * b.R + b.I * b.I) <- should be
             ^

I = (a.I * b.R + a.R * b.I) / (b.R * b.R + b.I * b.I)
    (a.I * b.R - a.R * b.I) / (b.R * b.R + b.I * b.I) <- should be
               ^

该测试代码的 运行 生成了这些结果(为了便于阅读而重新格式化):

(19.65+3.142i) + (19.68+2.718i) = (39.33+5.86i)
(19.65+3.142i) - (19.68+2.718i) = (-0.03+0.424i)
(19.65+3.142i) * (19.68+2.718i) = (378.172+115.243i)
(19.65+3.142i) / (19.68+2.718i) = (1.00142+0.021348i)
(19.65+3.142i) / (2+0i)         = (9.825+1.571i)
(19.65+3.142i) / (0+2i)         = (1.571-9.825i)
(19.65+3.142i) / (0+0i)         = Successfully caught divide-by-zero