3

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

4
  • 7
    Is there a reason you aren't asking your professor for additional clarification? Seems that that would be the proper academic course of action. Commented Sep 26, 2016 at 21:36
  • Seems to me this is more of a badly phrased question as the OP doesn't know how to phrase exactly what he's asking for. Commented Sep 26, 2016 at 21:43
  • 2
    I believe you are overthinking this: "loses it's worthiness cause then it's not a complex number." Your Complex class should define valid operations. If the rules are the same then how is that different from a "complex number"? Commented Sep 26, 2016 at 21:51
  • Yeah, I was not clear enough in my initial question I DO NOT expect u to do my homework for me. I am simply asking advice, I didn't want code. Thanks for your input though much appreciated @ Mar B, .. I have contacted him unfortunately this is Unisa, they are slow and tedious with replies and due date is in less than a week that's why I resorted to here @ David L, ... Commented Sep 27, 2016 at 16:07

4 Answers 4

4

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 )

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Keith, I appreciate it. :)
4

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):

  1. Mandelbrot set (Python, but understandable for C# programmers too)
  2. Mandelbrot algorithms (Pseudocode)

13 Comments

Can you describe what "use them seamlessly" means for the novices amongst us?
Why is a struct faster "in this case"? Are you specifically saying that there is a case where a struct would be slower?
@Enigmativity - Sure, I meant you can use them just like other numbers C# provides (int, single, double) with all common operators. So you can write c1 + c2 just as you would do it with other number types. And you can compare c1 < c1 directly (if (c1 < c2) ...).
@Enigmativity - Regarding your other question: I meant "struct" compared to "class": I have measured the time that this library takes to calculate a given mandelbrot set. Then I have replaced "struct" by "class" and measured it again. The "struct" implementation is much faster. With "struct" it took about 3 seconds (multi-threaded), with "class" it took about 5 seconds (also multi-threaded) to draw the picture (same program, same parameters).
In the inequality operator, shouldn't there be an or instead of an and..?
|
1

"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);

4 Comments

The way I understood it was that the app has to give /you/ the real and imaginary values?
@Almendro Your question is unclear to me then. You apparently have a Complex class handed to you that has Real and Imaginary properties, meaning if the app wants to give /you/ the real and imaginary values then the app just has to do: Console.WriteLine("Real number is: " + c.Real); Console.WriteLine("Imaginary number is: " + c.Imaginary);. The app "knows" which one is imaginary because the programmer explicitly made a property called Imaginary and the programmer explicitly only assigns inputs that are designated as "imginary" into that property.
Okay, makes sense yes what I wanted to do though is without making explicit properties for imaginary, have the program work out based on two any random inputs which the imaginary is. However, I think I'm over complicating it, and will just make explicit calls.
"have the program work out based on two any random inputs which the imaginary is" -- you can do that by parsing an input string, then validating that the string 1) has only one + sign, 2) after Split('+') against + there are only two elements, and 3) after Trim()ing, one and only one of those elements has the character i after it which is the imaginary part. Then you can pass in strings like, 3+5i, 5i + 3, 3+ 5i which parses into "real is 3 imaginary is 5", and strings like 3i + 5i or 3+5 throw an exception as being malformed and unsupported by you due to being ambiguous.
1

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...

1 Comment

Thanks, much appreciated that u took the time to reply. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.