1. 前言
在.net 中没有提供复数类的操作。第三方库Math.net中包含了复数的相关定义、矩阵、线性代数以及傅里叶变换等一整套数学操作。但当项目中只需简单计算复数时,引入库并非较好的选择,重新手写一个复数类效率更高,与项目的契合度也更好。
2. 复数类布局思路和代码实现
复数类编写不具有很大难度,但多数复数类均只支持使用实部虚部模式构造一个复数,而幅值相位模式也是构造复数的一个方式。现给出可以满足两种方法构造的复数类实现:
using System;
namespace MathUtil
{
public struct Complex : IComparable, IFormattable, IComparable<Complex>, IEquatable<Complex>
{
//一些有用的常量
private const double DoublePI = 2 * Math.PI;
private const double NegativePI = -1 * Math.PI;
public const double RadToDeg = 180.0 / Math.PI;
public const double DegToRad = Math.PI / 180.0;
//字段
private double _real;
private double _imag;
private double _magnitude;
private double _phase;
//私有的构造函数,外部不能直接通过含参的构造函数创建复数
private Complex(double real, double imag, double magnitude, double phase) : this()
{
_real = real;
_imag = imag;
_magnitude = magnitude;
_phase = phase;
}
//实部虚部和幅值相位,获取时直接获取,设置时进行更新
public double Real
{
get => _real;
set
{
_real = value;
this.UpdateFromRealImagMode();
}
}
public double Imag
{
get => _imag;
set
{
_imag = value;
this.UpdateFromRealImagMode();
}
}
public double Magnitude
{
get => _magnitude;
set
{
_magnitude = value;
this.UpdateFromMagniPhaseMode();
}
}
public double Phase
{
get => _phase;
set
{
_phase = value;
this.UpdateFromMagniPhaseMode();
}
}
//共轭复数,使用静态的工厂方法创建(工厂方法在下方)
public Complex Conjugate => Complex.FromRealImagMode(this._real, -1 * this._imag);
//判断值是否为非数字
public bool IsNaN => Double.IsNaN(this._real) || Double.IsNaN(this._imag);
//这里使用私有构造直接创建NaN的Complex
public static Complex NaN => new Complex(Double.NaN, Double.NaN, Double.NaN, Double.NaN);
//转换为NaN的Complex, 此处使用 ref 直接获取引用
public static void ToNaN(ref Complex target)
{
target._real = Double.NaN;
target._imag = Double.NaN;
target._magnitude = Double.NaN;
target._phase = Double.NaN;
}
//复制值, 此处使用 ref 直接获取引用
public static void CopyValue(ref Complex target, ref Complex source)
{
target._real = source._real;
target._imag = source._imag;
target._magnitude = source._magnitude;
target._phase = source._phase;
}
//静态的工厂方法,共两种
public static Complex FromRealImagMode(double real, double imag = 0.0)
{
double magnitude = 0;
double phase = 0;
if (real != 0 || imag != 0)
{
magnitude = Math.Sqrt