由于这个问题已经被提出一段时间,但我相信还有其他人对这个话题感兴趣,所以我决定发布最近在 C# 中实现的复数。因为复数是值类型,所以我使用了结构体而不是类(在这种情况下,结构体更快,我用一个简单的应用程序运行 Mandelbrot 算法 [请参见答案下面的链接] 来测量它),并重载了操作符如 +, -, *, /
以及比较操作符 <, >, =, !=, ==
,因此您可以无缝地使用它们(但是,因为复数是二维的,<
和 >
将与平方数量进行比较,而 ==
和 !=
将与等式进行比较)。
我使用了双精度,因为分形图形等需要高精度。但是,如果您的应用程序足够,则也可以使用单精度。
请注意,这需要覆盖 GetHashCode()
和 Equals(object obj)
。我还重载了 ++
和 --
操作符,尽管在复数世界中有几种可能的解释方法:递增/递减实部和虚部或只递增/递减其中之一?
此外,我创建了一个元组 (a, bi)
和复数之间的隐式转换,因此您可以轻松地初始化它们,例如:
complex a = (1, 2), b = (3, 4)
你甚至可以解析像这样的字符串:
string input = Console.ReadLine();
if (!complex.TryParse(input, out complex c))
Console.WriteLine("Syntax error");
else
Console.WriteLine($"Parsed value for c = {c}");
然后您可以像使用简单的东西一样使用它们。
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}");
为您提供输出
a - b = -2 - 2i
a + b = 4 + 6i
a * b = -5 + 10i
a / b = 0.44 + 0.08i
您甚至可以编写一个for循环,就像这样(请注意您有两个维度!):
for (complex u = (0,0); u <= (5, 5); u.Re++, u.Im++)
{
Console.WriteLine(u);
}
如果还需要进行比较:
if (u==(1, 1)) Console.WriteLine("u == 1+i");
所需的类实现如下:
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; }
public static complex operator --(complex c) { --c.Re; --c.Im; return c; }
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));
public static bool operator <(complex a, complex b) => AmountSqr(a) < AmountSqr(b);
public static bool operator >(complex a, complex b) => AmountSqr(a) > AmountSqr(b);
public static bool operator ==(complex a, complex b) => (a.Re == b.Re && a.Im == b.Im);
public static bool operator !=(complex a, complex b) => (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, a.Re*b.Im+a.Im*b.Re);
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);
public override string ToString()
=> $"{this.Re.ToString().Trim()} {(this.Im < 0 ? "-" : "+")} {Math.Abs(this.Im)}i";
public static bool TryParse(string complexNr, out complex result)
{
bool success = false;
result = (0, 0);
try
{
result = Parse(complexNr);
success = true;
} catch {}
return success;
}
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();
}
}
参考资料(Mandelbrot算法用于测量“complex”库的性能):
- 曼德博集合(Python,但对C#程序员也易懂)
- 曼德博算法(伪代码)