用于执行复数算术的 C# 类






4.64/5 (10投票s)
用于执行复数算术的 C# 类
引言
尽管 C# 语言在许多类型的项目中得到了相当成功的应用,但它在科学计算方面的能力仍有待证明。C# 是否能与 FORTRAN 和 C++ 在科学和数学项目领域相媲美,这个问题仍然存在。
复数运算
复数的算术和代数在科学和工程的许多领域都很重要。即使 C# 不支持内置的复数数据类型,也无法阻止您创建自己的复数类型。您可以使用具有值语义的 struct
来实现。本文的目的是介绍我尝试为 C# 设计一个复数运算类的过程。
Using the Code
struct Complex
完全包含在文件 Complex.cs 的 ComplexMath
命名空间中。下载中包含三个独立的程序文件,以及一个项目文档帮助文件。您可以通过引用 ComplexMath.dll 来运行程序,或者通过将 Complex.cs 文件简单地添加到项目中来直接使用 ComplexMath
库代码。在任何一种情况下,您都必须在主项目文件中添加 ComplexMath
; 头。如果您决定采用 DLL 方式,请先运行 CompexMath.sln 文件构建库(DLL),然后您可以生成两个 ComplexMath.dll 文件,分别位于 bin/Release 和 bin/Debug 目录下。
将库用作 DLL 的步骤
- 启动一个新的 C# 控制台应用程序。
- 构建 Debug 和 Release 版本。
- 将 ComplexMath.dll 的 Debug 和 Release 版本放入相应的 bin 文件夹中。
- 从“项目/添加引用”菜单中,找到所需版本(Debug 或 Release)的 ComplexMath.dll 并将其添加到项目中。
- 在您的程序文件中添加头:
using ComplexMath;
。 - 使用附带的 TestComplexMath.cs 文件作为您自己程序的原型。
您的测试程序应该类似于下面的示例,它简要演示了该库的许多功能。
using System.Collections.Generic;
using System.Text;
using ComplexMath;
namespace TestLib
{
class Program
{
static void Main(string[] args)
{
Complex z1, z2, z3; // instantiation
z1 = new Complex(1.0, -2.0);
z2 = new Complex(-3.0, -5.0);
z3 = new Complex(0.292342, -0.394875);
Console.WriteLine("instantiated complex numbers:");
Console.WriteLine(string.Format("z1 = {0}", z1));
Console.WriteLine(string.Format("z2 = {0}", z2));
Console.WriteLine(string.Format("z3 = {0}", z3));
// random complex numbers
z1 = Complex.Random();
z2 = Complex.Random();
z3 = Complex.Random();
Console.WriteLine("random generated:");
Console.WriteLine(string.Format("z1 = {0}", z1));
Console.WriteLine(string.Format("z2 = {0}", z2));
Console.WriteLine(string.Format("z3 = {0}", z3));
Console.WriteLine("basic properties:");
Console.WriteLine(string.Format
("z1.real = {0} z1.imag = {1}", z1.real, z1.imag));
Console.WriteLine(string.Format
("complex conjugate of z1 = {0}.", z1.Conjugate));
Console.WriteLine(string.Format
("complex modulus of z1 = {0}.", z1.Modulus));
Console.WriteLine(string.Format
("complex argument of z1 = {0}.", z1.Argument)); // operators
Console.WriteLine("operators:");
z3 = z1 + z2; Console.WriteLine(string.Format("z1 + z2 = {0}", z3));
z3 = z1 - z2; Console.WriteLine(string.Format("z1 - z2 = {0}", z3));
z3 = z1 * z2; Console.WriteLine(string.Format("z1 * z2 = {0}", z3));
z3 = z1 / z2; Console.WriteLine(string.Format("z1 / z2 = {0}", z3));
// transcendental functions
Console.WriteLine("transcendental functions:");
z3 = Complex.Sin(z1); Console.WriteLine(string.Format("Sin(z1) = {0}", z3));
z3 = Complex.Cos(z1); Console.WriteLine(string.Format("Cos(z1) = {0}", z3));
z3 = Complex.Tan(z1); Console.WriteLine(string.Format("Tan(z1) = {0}", z3));
z3 = Complex.Sinh(z1);
Console.WriteLine(string.Format("Sinh(z1) = {0}", z3));
z3 = Complex.Cosh(z1);
Console.WriteLine(string.Format("Cosh(z1) = {0}", z3));
z3 = Complex.Tanh(z1);
Console.WriteLine(string.Format("Tanh(z1) = {0}", z3));
z3 = Complex.Exp(z1); Console.WriteLine(string.Format("Exp(z1) = {0}", z3));
z3 = Complex.Log(z1); Console.WriteLine(string.Format("Log(z1) = {0}", z3));
z3 = Complex.Log10(z1);
Console.WriteLine(string.Format("Log10(z1) = {0}", z3)); // roots
Console.WriteLine("roots:");
z3 = Complex.Sqrt(z1);
Console.WriteLine(string.Format("Sqrt(z1) = {0}", z3));
Console.WriteLine("k 4th roots:");
for (long k = 0; k < 4; k++)
{
z3 = Complex.NthRoot(z1, 4, k);
Console.WriteLine(string.Format("NthRoot(z1, 4, {0}) = {1}",k, z3));
} Console.WriteLine("the five 5th roots of unity:");
Complex z = new Complex(1.0, 0.0);
for (long k = 0; k < 5; k++)
{
z3 = Complex.NthRoot(z, 5, k);
Console.WriteLine
(string.Format("{0}th 5th root of unity = {1}", k, z3));
}
// powers
Console.WriteLine("powers:");
int n = 7;
z3 = Complex.Pow(z1, z2);
Console.WriteLine(string.Format("Complex.Pow(z1, z2) = {0}", z3));
z3 = Complex.Pow(z1, n);
Console.WriteLine(string.Format("Complex.Pow(z1, {0}) = {1}", n, z3));
// display
Console.WriteLine("display:");
z1.Show();
z1.ShowPolar();
Console.WriteLine(string.Format("polar form of z1 = {0}.", z1.Polar()));
// debug tracing
z1.Dump();
}// Program
}// TestLib
附带的 TestLib
程序演示了 Complex struct
的所有功能。值得一提的是,复数可以表示为大多数高中代数学生熟悉的直角坐标形式,也可以表示为需要更高级三角学、棣莫弗定理和欧拉恒等式知识的更复杂的极坐标形式。如果您感兴趣,可以在网上查阅相关信息。
请注意,所有初始化输入都假定您使用的是复数的直角坐标形式,这意味着实部沿阿甘图的 x 轴测量,虚部沿 y 轴测量。但是,该程序可以通过使用 ShowPolar()
和 Polar()
方法以及 Argument
和 Modulus
属性(见上文)来输出极坐标形式的分量——即模 |z|
和辐角(theta)。
由于复数可以进行加、减、乘、除运算,因此方便地为此类运算提供运算符。因此,我们已经包含了这些运算符。
历史
似乎有许多关于 C# 复数处理代码的帖子。其中包括:
- Karl Tarbet 的 C# 和 VB.NET 复数数学库
- Boxing Wang 的 Complex struct,是对 Tarbet 文章的评论
- Eran Kampf 的 Sharp3D.Math - .NET 的 3D 数学库
- Dan2178 的类,用于本机处理复数,声称包含超过 100 个方法、运算符和重载
- 有些软件公司销售 extensive collections of C# scientific and engineering software,价格约为 1000.00 美元。
尽管我从事科学数学和统计编程已超过 10 年,但这篇是我尝试发布的第一个文章。我很快了解到,有许多比我更聪明、更优秀的程序员已经用 C# 做得更好。对我来说,这是一次极好的学习经历,既学习了使用 C# 进行科学计算的许多陷阱,也学会了向他人解释我的代码的作用。
陷阱
C# 类赋值运算符是自动生成的且无法重写,这似乎造成了一个问题,特别是对于来自 C++ 背景的人来说。一旦进行赋值,赋值者和被赋值者就通过一个公共指针绑定在一起。改变一个,另一个也会改变。为了解决这个问题,人们需要实现 ICloneable
,这可能相当繁琐和复杂。出于这个原因,我选择使用 struct
而不是类。我仍在学习 C#。
我计划更新和改进此代码供我自己使用,以及供任何希望使用它的人使用,并在将来做得更好。您可以以任何您希望的方式使用此代码。礼貌和专业的做法是注明原作者的功劳。请将任何评论、批评或错误报告到下方的论坛。