Reputation: 67
I have an assignment to write a Complex number implementation :-
Complex c = new Complex(1.2,2.0)
Write properties real and Imaginary to get the real and imaginary part of a complex number. which are used like this:
double x = c.Real;
Write a method to add two complex numbers and return their sum. The real part is the sum of the two real parts, and the imaginary part the sum of the two imaginary parts.
Complex c = c1.Sum(c2);
Write a method to calculate the product of the two complex numbers. If one number has components x1
and y1
and the second number has components, x2
and y2
:
the real part of the product = x1 *x2 - y1 *y2
;
the imaginary part = x1 * y2 + x2 *y1
;
So I know and am pretty confident-ish with complex numbers manually such as 4 +5i
where 5i
is imaginary,
My questions is, I'm not sure how to get the app to know which one is imaginary, unless I make on input a predefined imaginary number.. The minute I do that though the " app " loses it's worthiness cause then it's not an complex number just some random calc app. Basically I have no clue how to proceed.. Thanks
Upvotes: 3
Views: 16532
Reputation: 27001
Since this question was asked a while ago, but I am sure there are others who are interested in this topic, I decided to post the implementation for complex numbers in C# I have made recently.
Because complex numbers are value types, I used a struct instead of a class (a struct is faster in this case, which I found out with the help of a simple app I wrote running a Mandelbrot algorithm [see links below the answer] to measure it) and have overloaded operators like +, -, *, /
as well as comparison operators <, >, =, !=, ==
so you can use them seamlessly (however because complex numbers are two-dimensional, <
and >
will compare against the squared amount, while ==
and !=
compare against equality).
I have used double precision, because fractal graphic and such require high accuracy. But you could also use single precision if that's sufficient for your application.
Note that this requires to override GetHashCode()
and Equals(object obj)
as well. I have also overloaded ++
and --
operators, although in the complex world there are several possible ways to interpret this: increment/decrement real and imaginary parts or just one of them?
Also I have created an implicit conversion between a tuple (a, bi)
and the complex numbers so you can easily initialize them like:
complex a = (1, 2), b = (3, 4); // via tuples (re, im)
You can even parse strings like:
string input = Console.ReadLine();
if (!complex.TryParse(input, out complex c))
Console.WriteLine("Syntax error");
else
Console.WriteLine($"Parsed value for c = {c}");
Then you can use them as simply as
var w = a - b; Console.WriteLine($"a - b = {w}");
var x = a + b; Console.WriteLine($"a + b = {x}");
var y = a * b; Console.WriteLine($"a * b = {y}");
var z = a / b; Console.WriteLine($"a / b = {z}");
Giving you the output
a - b = -2 - 2i
a + b = 4 + 6i
a * b = -5 + 10i
a / b = 0.44 + 0.08i
You can even write a for loop just as (notice you have 2 dimensions!):
for (complex u = (0,0); u <= (5, 5); u.Re++, u.Im++)
{
Console.WriteLine(u);
}
And if comparisons are also possible:
if (u==(1, 1)) Console.WriteLine("u == 1+i");
The required class is implemented as follows:
/// <summary>
/// Complex numbers
/// Written by Matt, 2022
///
/// https://stackoverflow.com/a/70936453/1016343
/// </summary>
struct complex
{
public double Re, Im;
public complex(double re, double im)
{
this.Re = re; this.Im = im;
}
public static complex operator ++(complex c) { ++c.Re; ++c.Im; return c; } // not the only way one can implement this
public static complex operator --(complex c) { --c.Re; --c.Im; return c; } // not the only way one can implement this
public static complex operator +(complex a, complex b) => new complex(a.Re + b.Re, a.Im + b.Im);
public static complex operator -(complex a, complex b) => new complex(a.Re - b.Re, a.Im - b.Im);
public static double AmountSqr(complex c) => c.Re * c.Re + c.Im + c.Im;
public static double Amount(complex c) => Math.Sqrt(AmountSqr(c));
/// <summary>Compares the amount of both complex numbers, returns true if |a|<|b|.</summary>
public static bool operator <(complex a, complex b) => AmountSqr(a) < AmountSqr(b);
/// <summary>Compares the amount of both complex numbers, returns true if |a|>|b|.</summary>
public static bool operator >(complex a, complex b) => AmountSqr(a) > AmountSqr(b);
/// <summary>Compares the both complex numbers, returns true if a == b.</summary>
public static bool operator ==(complex a, complex b) => (a.Re == b.Re && a.Im == b.Im);
/// <summary>Compares the both complex numbers, returns true if a != b.</summary>
public static bool operator !=(complex a, complex b) => (a.Re != b.Re || a.Im != b.Im);
// (a+bi)(c+di) = ac-bd + (ad+bc)i
public static complex operator *(complex a, complex b)
=> new complex(a.Re*b.Re-a.Im*b.Im, a.Re*b.Im+a.Im*b.Re);
// (a+bi)/(c+di) = (ac+bd)/(c*c + d*d) + i(bc-ad)/(c*c + d*d)
public static complex operator /(complex a, complex b)
{
var divisor = (b.Re * b.Re + b.Im * b.Im);
return new complex((a.Re*b.Re+a.Im*b.Im)/divisor, (a.Im*b.Re-a.Re*b.Im)/divisor);
}
public static implicit operator complex((double real, double imag) c)
=> new complex(c.real, c.imag); // via tuples (re, im)
public override string ToString()
=> $"{this.Re.ToString().Trim()} {(this.Im < 0 ? "-" : "+")} {Math.Abs(this.Im)}i";
/// <summary>Tries to convert string expressions like "2+3i" or "5-7i" to complex</summary>
public static bool TryParse(string complexNr, out complex result)
{
bool success = false;
result = (0, 0);
try
{
result = Parse(complexNr);
success = true;
} catch {}
return success;
}
/// <summary>Converts string expressions like "2+3i" or "5-7i" to complex</summary>
public static complex Parse(string complexNr)
{
complex result = (0, 0);
try
{
if (complexNr.Contains("-")) complexNr = complexNr.Replace("-", "+-");
var tr = complexNr.Split("+").Select(s => s.Trim()).ToArray();
var realStr = tr[0]; var imagStr = tr[1].TrimEnd('i').Trim();
result = (double.Parse(realStr), double.Parse(imagStr));
}
catch (Exception ex)
{
throw new SyntaxErrorException("Invalid syntax for complex number. Allowed is 'a+bi' or 'a-bi'", ex);
}
return result;
}
public override bool Equals(object obj)
{
return (obj == null) ? false : (this == (complex)obj);
}
public override int GetHashCode()
{
var hash = new HashCode();
hash.Add(this.Re); hash.Add(this.Im);
return hash.ToHashCode();
}
}
References (Mandelbrot algorithms to measure performance of "complex" library):
Upvotes: 4
Reputation: 32750
What is a complex number? Well, its a number that has a real part, and an imaginary part. The imaginary part is itself a real number multiplied by this curious imaginary constant i such that i * i = -1
. There is nothing more to it, so implement it that way. Why would that make your code lose any worthiness?
public struct Complex
{
public static readonly ImaginaryOne = new Complex(0, 1);
public doube Real { get; }
public double Imaginary { get; }
public Complex(double real, double imaginary)
{
Real = real;
Imaginary = imaginary;
}
}
And the rest is just boilerplate...
Upvotes: 1
Reputation: 1799
"I'm not sure how to get the app to know which one is imaginary" -- Here's one way:
Console.WriteLine("Input the real part of the complex number:");
var real = double.Parse(Console.ReadLine());
Console.WriteLine("Input the imaginary part of the complex number:");
var imaginary = double.Parse(Console.ReadLine());
var complexNumber = new Complex(real, imaginary);
Upvotes: 1
Reputation: 44288
Seems from your question you are confused about the construction of the Complex number. Here's a template to get you started.
public class Complex
{
public Complex(double real, double imaginary)
{
}
}
then start with
static void Main(string[] args)
{
Complex c1 = new Complex(1.2,2.0)
Complex c2 = new Complex(1,3.0)
Complex c3 = c1.Sum(c2);
Console.WriteLine(c3.Real);
Console.WriteLine(c3.Imaginary);
}
and get that working ( put whatever numbers you like in for starters )
Upvotes: 4