如何修复我的 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 有两个成员变量,n
和 d
。您似乎试图将值放入 (non-existent) a
和 b
成员变量中。
结局不会很好:-)
我建议,首先,使用让您的意图更清晰的变量名。例如,成员变量 n
和 d
最好命名为 m_real
和 m_imag
(n
和 d
看起来它们应该代表分子和分母,但这与复数(a)没有任何关系。
通过使用合适的变量名,阅读代码应该足以弄清楚发生了什么,并且您不太可能混淆 class 的成员变量和对象(另外 不应命名为 n
和 d
).
(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 运算符时,
add
、sub
等没有什么意义。
- 使用构造函数(或运算符)创建了所有复数。您应该 而不是 尝试更改 classes 内部(私有)数据。如果必须这样做,请使用 setter 函数。
- 对您的输出流代码进行了(非常轻微的)调整以改进格式。同样,这就是您应该用来输出对象的方法,而不是 试图直接访问私有数据。
- 修复了 divide-by-zero 检测。只有当 实部和虚部都为零时才会发生这种情况,而如果 either 为零,则您将其提高。那意味着你永远无法将某物除以二,因为虚部为零,
(2+0i)
.
- 使部件成为浮点数而不是整数。如果你愿意,你可以改回它们,但浮点数在一般用途中可能更好 class.
- 修正了乘法和除法公式。
为了解释最后一个要点,乘法 a * b
是,其中 a
和 b
是复数,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
我的 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 有两个成员变量,n
和 d
。您似乎试图将值放入 (non-existent) a
和 b
成员变量中。
结局不会很好:-)
我建议,首先,使用让您的意图更清晰的变量名。例如,成员变量 n
和 d
最好命名为 m_real
和 m_imag
(n
和 d
看起来它们应该代表分子和分母,但这与复数(a)没有任何关系。
通过使用合适的变量名,阅读代码应该足以弄清楚发生了什么,并且您不太可能混淆 class 的成员变量和对象(另外 不应命名为 n
和 d
).
(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 运算符时,
add
、sub
等没有什么意义。 - 使用构造函数(或运算符)创建了所有复数。您应该 而不是 尝试更改 classes 内部(私有)数据。如果必须这样做,请使用 setter 函数。
- 对您的输出流代码进行了(非常轻微的)调整以改进格式。同样,这就是您应该用来输出对象的方法,而不是 试图直接访问私有数据。
- 修复了 divide-by-zero 检测。只有当 实部和虚部都为零时才会发生这种情况,而如果 either 为零,则您将其提高。那意味着你永远无法将某物除以二,因为虚部为零,
(2+0i)
. - 使部件成为浮点数而不是整数。如果你愿意,你可以改回它们,但浮点数在一般用途中可能更好 class.
- 修正了乘法和除法公式。
为了解释最后一个要点,乘法 a * b
是,其中 a
和 b
是复数,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