I have got some problems with my main.cpp.There are some places where I do not know what I have to write to make my code work well. I will write in my code where the problems are. I write the Problem word where my code is wrong. Does anybody have an idea what I have to change to make my code work? My code is about Complex numbers add,sub,divide,mul.
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;
}
CodePudding user response:
Your Complex
class has two member variables, n
and d
. You appear to be trying to put values into the (non-existent) a
and b
member variables.
That's not going to end well :-)
I would suggest, for a start, using variable names that make your intent clearer. For example, member variables n
and d
would be far better named as something like m_real
and m_imag
(n
and d
look like they should represent numerator and denominator, but that has nothing to do with complex numbers(a)).
By using decent variable names, reading of the code should be enough to figure out what's happening and you're unlikely to get confused between member variables and objects of the class (which also shouldn't be named n
and d
).
(a) To be honest, it looks like you've re-tasked some code meant to do rationals to be used as complex numbers. I base this on the variable naming and the fact your Complex
constructor has:
Complex(int _n = 0, int _d = 1) : n(_n), d(_d)
{
if(d == 0)
{
throw NullDivision();
}
}
I can see no reason why the imaginary part of a complex number would default to one, nor why you would throw a NullDivision
exception if it was zero. That would basically remove the entire set of real numbers from your complex class.
So, it's even more important that you use better names so that you can figure out why these re-tasked things are wrong.
I'm going to give you an example of how a professional developer would code up something like this (albeit without the copious comments I normally have).
I wouldn't suggest using this if this is educational classwork since you're likely to get pinged for plagiarism but it should serve as a guide on how to do it.
#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;
}
As part of this, I:
- Got rid of superfluous stuff. There's little point having
add
,sub
, and so on, when you can just use the built-in operators. - Created all complex numbers using the constructors (or operators). You should not be trying to change a classes internal (private) data. If you must do that, use a setter function.
- Made a (very slight) adjustment to your output stream code to improve the format. And again, this is what you should use to output an object, not attempting to directly access private data.
- Fixed the divide-by-zero detection. This only happens if both the real and imaginary parts are zero whereas you raised it if either were. That would bean you could never divide something by two since the imaginary part is zero,
(2 0i)
. - Made the parts floating point rather than integers. You can change them back if you wish but the floating point is probably better in a general purpose class.
- Fixed your multiplication and division formulae.
To explain that final bullet point, what you had for multiplication a * b
was, where a
and b
are the complex numbers, R
is the real part, I
the imaginary:
R = a.R * b.R - a.I * b.I # correct.
I = a.R * b.I - a.I * b.R # should be adding, not subtracting
^
For division a / b
, you had:
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
^
The run of that test code generates these results (reformatted for readability):
(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