我的C++ 的基础一直都不太扎实,最近有点空闲时间,找了本 C++ Primer 仔细的读了读。看完运算符重载那一章时,就想到写个复数类来练一练手。
实际上 C++ 中是有复数类的,而且还是个模版类,比我这个类用起来更灵活。不过我的类也有自己的特点,就是支持相当多的数学函数,那些函数相应的代码是从 GSL 中借来的,所以计算结果还算是可靠的,大多数的函数的计算结果 都用 Mathematica 验算过了,看起来还算是挺靠谱的。
下面先贴出头文件。
#ifndef COMPLEX_H
#define COMPLEX_H
#include <iostream>
class Complex
{
public:
Complex(const Complex &z);
Complex(double x = 0.0, double y = 0.0);
~Complex();
double real() const {return dat[0];}
double image() const {return dat[1];}
double abs() const {return hypot(dat[0], dat[1]);}
void set(double x, double y) {dat[0] = x; dat[1] = y;}
inline double arg() const;
inline double abs2() const;
inline double logabs () const;
Complex conjugate() const;
Complex inverse() const;
Complex operator +(const Complex &other) const;
Complex operator +(const double &other) const;
Complex operator -(const Complex &other) const;
Complex operator -(const double &other) const;
Complex operator *(const Complex &other) const;
Complex operator *(const double &other) const;
Complex operator /(const Complex &other) const;
Complex operator /(const double &other) const;
void operator +=(const Complex &other);
void operator +=(const double &other);
void operator -=(const Complex &other);
void operator -=(const double &other);
void operator *=(const Complex &other);
void operator *=(const double &other);
void operator /=(const Complex &other);
void operator /=(const double &other);
Complex& operator =(const Complex &other);
Complex& operator =(const double &other);
private:
double dat[2];
friend std::ostream& operator << (std::ostream&, const Complex & z);
friend Complex operator -(const Complex &other);
};
Complex sqrt(const Complex& a);
Complex exp(const Complex& a);
Complex pow(const Complex& a, const Complex& b);
Complex pow(const Complex& a, double b);
Complex log(const Complex& a);
Complex log10 (const Complex &a);
Complex log(const Complex &a, const Complex &b);
// 三角函数
Complex sin (const Complex& a);
Complex cos (const Complex& a);
Complex tan (const Complex& a);
Complex cot (const Complex& a);
Complex sec (const Complex& a);
Complex csc (const Complex& a);
// 反三角函数
Complex arcsin_real (double a);
Complex arccos_real(double a);
Complex arcsec_real (double a);
Complex arctan_real (double a);
Complex arccsc_real(double a);
Complex arcsin (const Complex& a);
Complex arccos (const Complex& a);
Complex arctan (const Complex& a);
Complex arcsec (const Complex& a);
Complex arccsc (const Complex& a);
Complex arccot (const Complex& a);
/**********************************************************************
* Complex Hyperbolic Functions
**********************************************************************/
Complex sinh (const Complex& a);
Complex cosh (const Complex& a);
Complex tanh (const Complex& a);
Complex sech (const Complex& a);
Complex csch (const Complex& a);
Complex coth (const Complex& a);
/**********************************************************************
* Inverse Complex Hyperbolic Functions
**********************************************************************/
Complex arccoth (const Complex& a);
Complex arccsch (const Complex& a);
Complex arcsech (const Complex& a);
Complex arctanh_real (double a);
Complex arctanh (const Complex& a);
Complex arccosh_real (double a);
Complex arccosh (const Complex& a);
Complex arcsinh (const Complex& a);
Complex polar(double r, double theta);
double fabs(const Complex &z);
#endif // COMPLEX_H
复数的实部和虚部存在了一个数组中,而不是放到两个double型变量中,这样做也是遵循了 GSL 的代码,据GSL 的作者解释,这样可以最大限度的保证 实部和虚部是连续放置的。代码还算简单,这里就对几个重点做些解释。
Complex operator +(const Complex &other) const;
operator + 必须要声明为 const。否则下面的代码无法通过编译。
const Complex a(1, 2);
const Complex b(2, 3);
Complex c = a + b;
Complex operator -(const Complex &other);
这个函数是为了类似如下代码使用的
c = -a + b;
实际上这个函数不用声明为 友元函数,因为它不需要访问越权访问Complex 的私有变量。之所以这么写只是想用一下 friend 关键字。不过我个人认为外部函数还是不应该越权访问类的私有变量的,因此 friend 用的越少越好。所以后面实现的各种数学函数都没有声明为友元函数。
下面是Complex 的基本实现。
#include "complex.h"
#include <cmath>
Complex::Complex(double x, double y)
{
dat[0] = x;
dat[1] = y;
}
Complex::Complex(const Complex &z)
{
dat[0] = z.dat[0];
dat[1] = z.dat[1];
}
Complex::~Complex()
{
}
double Complex::arg() const
{
double x = dat[0];
double y = dat[1];
if (x == 0.0 && y == 0.0)
{
return 0;
}
return std::atan2 (y, x);
}
double Complex::abs2() const
{
double x = dat[0];
double y = dat[1];
return (x * x + y * y);
}
double Complex::logabs () const
{
double xabs = fabs (dat[0]);
double yabs = fabs (dat[1]);
double max, u;
if (xabs >= yabs)
{
max = xabs;
u = yabs / xabs;
}
else
{
max = yabs;
u = xabs / yabs;
}
/* Handle underflow when u is close to 0 */
return log (max) + 0.5 * log1p (u * u);
}
Complex Complex::conjugate() const
{
Complex z(dat[0], -dat[1]);
return z;
}
Complex Complex::inverse() const
{
double s = 1.0 / fabs (*this);
double x = this->real();
double y = this->image();
Complex z(x * s * s, - y * s * s);
return z;
}
void Complex::operator +=(const Complex &other)
{
dat[0] += other.dat[0];
dat[1] += other.dat[1];
}
void Complex::operator +=(const double &other)
{
dat[0] += other;
}
void Complex::operator -=(const Complex &other)
{
dat[0] -= other.dat[0];
dat[1] -= other.dat[1];
}
void Complex::operator -=(const double &other)
{
dat[0] -= other;
}
void Complex::operator *=(const Complex &other)
{
double x, y;
x = (dat[0] * other.dat[0] - dat[1] * other.dat[1]);
y = (dat[1] * other.dat[0] + dat[0] * other.dat[1]);
dat[0] = x;
dat[1] = y;
}
void Complex::operator *=(const double &other)
{
dat[0] = dat[0] * other;
dat[1] = dat[1] * other;
}
void Complex::operator /=(const Complex &other)
{
double x, y;
double a = other.dat[0] * other.dat[0] + other.dat[1] * other.dat[1];
x = ((dat[0] * other.dat[0]) + (dat[1] * other.dat[1])) / a;
y = ((dat[1] * other.dat[0]) - (dat[0] * other.dat[1])) / a;
dat[0] = x;
dat[1] = y;
}
void Complex::operator /=(const double &other)
{
dat[0] = dat[0]/other;
dat[1] = dat[1]/other;
}
Complex Complex::operator+(const Complex &other) const
{
Complex temp(*this);
temp += other;
return temp;
}
Complex Complex::operator +(const double &other) const
{
Complex temp(*this);
temp += other;
return temp;
}
Complex Complex::operator -(const Complex &other) const
{
Complex temp(*this);
temp -= other;
return temp;
}
Complex Complex::operator -(const double &other) const
{
Complex temp(*this);
temp -= other;
return temp;
}
Complex operator -(const Complex &other)
{
Complex temp(-other.real(), -other.image());
return temp;
}
Complex Complex::operator *(const Complex &other) const
{
Complex temp(*this);
temp *= other;
return temp;
}
Complex Complex::operator *(const double &other) const
{
Complex temp(*this);
temp *= other;
return temp;
}
Complex Complex::operator /(const Complex &other) const
{
Complex temp(*this);
temp /= other;
return temp;
}
Complex Complex::operator /(const double &other) const
{
Complex temp(*this);
temp /= other;
return temp;
}
Complex& Complex::operator =(const Complex &other)
{
this->dat[0] = other.dat[0];
this->dat[1] = other.dat[1];
return *this;
}
Complex& Complex::operator =(const double &other)
{
this->dat[0] = other;
this->dat[1] = 0;
return *this;
}
std::ostream& operator << (std::ostream& out, const Complex & z)
{
out << "real = " << z.dat[0] << std::endl;
out << "image = " << z.dat[1] << std::endl;
return out;
}
Complex polar(double r, double theta)
{
Complex z(r * cos(theta), r * sin(theta));
return z;
}
double fabs(const Complex &z)
{
return hypot(z.real(), z.image());
}
Complex sqrt(const Complex& a)
{
Complex z;
if (a.real() == 0.0 && a.image() == 0.0)
{
z = Complex(0, 0);
}
else
{
double x = fabs (a.real());
double y = fabs (a.image());
double w;
if (x >= y)
{
double t = y / x;
w = sqrt (x) * sqrt (0.5 * (1.0 + sqrt (1.0 + t * t)));
}
else
{
double t = x / y;
w = sqrt (y) * sqrt (0.5 * (t + sqrt (1.0 + t * t)));
}
if (a.real() >= 0.0)
{
double ai = a.image();
z.set (w, ai / (2.0 * w));
}
else
{
double ai = a.image();
double vi = (ai >= 0) ? w : -w;
z.set( ai / (2.0 * vi), vi);
}
}
return z;
}
Complex exp(const Complex& a)
{
double rho = exp (a.real());
double theta = a.image();
Complex z(rho * cos (theta), rho * sin (theta));
return z;
}
Complex pow(const Complex& a, const Complex& b)
{ /* z=a^b */
Complex z;
if (a.real() == 0 && a.image() == 0.0)
{
if (b.real() == 0 && b.image() == 0.0)
{
z.set(1.0, 0.0);
}
else
{
z.set( 0.0, 0.0);
}
}
else if (b.real() == 1.0 && b.image() == 0.0)
{
return a;
}
else if (b.real() == -1.0 && b.image() == 0.0)
{
return a.inverse();
}
else
{
double logr = a.logabs();
double theta = a.arg();
double br = b.real(), bi = b.image();
double rho = exp (logr * br - bi * theta);
double beta = theta * br + bi * logr;
z.set( rho * cos (beta), rho * sin (beta));
}
return z;
}
Complex pow(const Complex &a, double b)
{ /* z=a^b */
Complex z;
if (a.real() == 0 && a.image() == 0)
{
if (b == 0)
{
z.set( 1, 0);
}
else
{
z.set( 0, 0);
}
}
else
{
double logr = a.logabs();
double theta = a.arg();
double rho = exp (logr * b);
double beta = theta * b;
z.set( rho * cos (beta), rho * sin (beta));
}
return z;
}
Complex log (const Complex &a)
{ /* z=log(a) */
double logr = a.logabs();
double theta = a.arg();
Complex z(logr, theta);
return z;
}
Complex log10 (const Complex &a)
{ /* z = log10(a) */
return log (a) / log (10.0);
}
Complex log(const Complex &a, const Complex &b)
{
return log (a) / log (b);
}
Complex sin (const Complex& a)
{ /* z = sin(a) */
double R = a.real(), I = a.image();
Complex z;
if (I == 0.0)
{
/* avoid returing negative zero (-0.0) for the imaginary part */
z.set( sin (R), 0.0);
}
else
{
z.set( sin (R) * cosh (I), cos (R) * sinh (I));
}
return z;
}
Complex cos (const Complex& a)
{
double R = a.real(), I = a.image();
Complex z;
if (I == 0.0)
{
/* avoid returing negative zero (-0.0) for the imaginary part */
z.set(cos (R), 0.0);
}
else
{
z.set( cos (R) * cosh (I), sin (R) * sinh (-I));
}
return z;
}
Complex tan (const Complex& a)
{
double R = a.real(), I = a.image();
Complex z;
if (fabs (I) < 1)
{
double D = pow (cos (R), 2.0) + pow (sinh (I), 2.0);
z.set( 0.5 * sin (2 * R) / D, 0.5 * sinh (2 * I) / D);
}
else
{
double u = exp (-I);
double C = 2 * u / (1 - pow (u, 2.0));
double D = 1 + pow (cos (R), 2.0) * pow (C, 2.0);
double S = pow (C, 2.0);
double T = 1.0 / tanh (I);
z.set( 0.5 * sin (2 * R) * S / D, T / D);
}
return z;
}
Complex cot (const Complex& a)
{ /* z = cot(a) */
Complex z = tan (a);
return z.inverse();
}
Complex sec (const Complex& a)
{
Complex z = cos (a);
return z.inverse();
}
Complex csc (const Complex& a)
{
Complex z = sin (a);
return z.inverse();
}
Complex arcsin_real(double a)
{ /* z = arcsin(a) */
Complex z;
if (fabs (a) <= 1.0)
{
z.set( asin (a), 0.0);
}
else
{
if (a < 0.0)
{
z.set( -M_PI_2, acosh (-a));
}
else
{
z.set( M_PI_2, -acosh (a));
}
}
return z;
}
Complex arcsin (const Complex& a)
{ /* z = arcsin(a) */
double R = a.real(), I = a.image();
Complex z;
if (I == 0)
{
z = arcsin(R);
}
else
{
double x = fabs (R), y = fabs (I);
double r = hypot (x + 1, y), s = hypot (x - 1, y);
double A = 0.5 * (r + s);
double B = x / A;
double y2 = y * y;
double real, imag;
const double A_crossover = 1.5, B_crossover = 0.6417;
if (B <= B_crossover)
{
real = asin (B);
}
else
{
if (x <= 1)
{
double D = 0.5 * (A + x) * (y2 / (r + x + 1) + (s + (1 - x)));
real = atan (x / sqrt (D));
}
else
{
double Apx = A + x;
double D = 0.5 * (Apx / (r + x + 1) + Apx / (s + (x - 1)));
real = atan (x / (y * sqrt (D)));
}
}
if (A <= A_crossover)
{
double Am1;
if (x < 1)
{
Am1 = 0.5 * (y2 / (r + (x + 1)) + y2 / (s + (1 - x)));
}
else
{
Am1 = 0.5 * (y2 / (r + (x + 1)) + (s + (x - 1)));
}
imag = log1p (Am1 + sqrt (Am1 * (A + 1)));
}
else
{
imag = log (A + sqrt (A * A - 1));
}
z.set( (R >= 0) ? real : -real, (I >= 0) ? imag : -imag);
}
return z;
}
Complex arccos (const Complex& a)
{ /* z = arccos(a) */
double R = a.real(), I = a.image();
Complex z;
if (I == 0)
{
z = arccos(R);
}
else
{
double x = fabs (R), y = fabs (I);
double r = hypot (x + 1, y), s = hypot (x - 1, y);
double A = 0.5 * (r + s);
double B = x / A;
double y2 = y * y;
double real, imag;
const double A_crossover = 1.5, B_crossover = 0.6417;
if (B <= B_crossover)
{
real = acos (B);
}
else
{
if (x <= 1)
{
double D = 0.5 * (A + x) * (y2 / (r + x + 1) + (s + (1 - x)));
real = atan (sqrt (D) / x);
}
else
{
double Apx = A + x;
double D = 0.5 * (Apx / (r + x + 1) + Apx / (s + (x - 1)));
real = atan ((y * sqrt (D)) / x);
}
}
if (A <= A_crossover)
{
double Am1;
if (x < 1)
{
Am1 = 0.5 * (y2 / (r + (x + 1)) + y2 / (s + (1 - x)));
}
else
{
Am1 = 0.5 * (y2 / (r + (x + 1)) + (s + (x - 1)));
}
imag = log1p (Am1 + sqrt (Am1 * (A + 1)));
}
else
{
imag = log (A + sqrt (A * A - 1));
}
z.set( (R >= 0) ? real : M_PI - real, (I >= 0) ? -imag : imag);
}
return z;
}
Complex arccos_real(double a)
{ /* z = arccos(a) */
Complex z;
if (fabs (a) <= 1.0)
{
z.set( acos (a), 0);
}
else
{
if (a < 0.0)
{
z.set( M_PI, -acosh (-a));
}
else
{
z.set( 0, acosh (a));
}
}
return z;
}
Complex arctan (const Complex& a)
{ /* z = arctan(a) */
double R = a.real(), I = a.image();
Complex z;
if (I == 0)
{
z.set( atan (R), 0);
}
else
{
/* FIXME: This is a naive implementation which does not fully
take into account cancellation errors, overflow, underflow
etc. It would benefit from the Hull et al treatment. */
double r = hypot (R, I);
double imag;
double u = 2 * I / (1 + r * r);
/* FIXME: the following cross-over should be optimized but 0.1
seems to work ok */
if (fabs (u) < 0.1)
{
imag = 0.25 * (log1p (u) - log1p (-u));
}
else
{
double A = hypot (R, I + 1);
double B = hypot (R, I - 1);
imag = 0.5 * log (A / B);
}
if (R == 0)
{
if (I > 1)
{
z.set( M_PI_2, imag);
}
else if (I < -1)
{
z.set( -M_PI_2, imag);
}
else
{
z.set( 0, imag);
};
}
else
{
z.set( 0.5 * atan2 (2 * R, ((1 + r) * (1 - r))), imag);
}
}
return z;
}
Complex arcsec (const Complex& a)
{ /* z = arcsec(a) */
Complex z = a.inverse();
return arccos(z);
}
Complex arcsec_real (double a)
{ /* z = arcsec(a) */
Complex z;
if (a <= -1.0 || a >= 1.0)
{
z.set( acos (1 / a), 0.0);
}
else
{
if (a >= 0.0)
{
z.set( 0, acosh (1 / a));
}
else
{
z.set( M_PI, -acosh (-1 / a));
}
}
return z;
}
Complex arccsc (const Complex& a)
{ /* z = arccsc(a) */
Complex z = a.inverse();
return arcsin (z);
}
Complex arccsc_real(double a)
{ /* z = arccsc(a) */
Complex z;
if (a <= -1.0 || a >= 1.0)
{
z.set( asin (1 / a), 0.0);
}
else
{
if (a >= 0.0)
{
z.set( M_PI_2, -acosh (1 / a));
}
else
{
z.set(-M_PI_2, acosh (-1 / a));
}
}
return z;
}
Complex arccot (const Complex& a)
{ /* z = arccot(a) */
Complex z;
if (a.real() == 0.0 && a.image() == 0.0)
{
z.set( M_PI_2, 0);
}
else
{
z = a.inverse();
z = arctan (z);
}
return z;
}
Complex sinh (const Complex& a)
{ /* z = sinh(a) */
double R = a.real(), I = a.image();
Complex z;
z.set( sinh (R) * cos (I), cosh (R) * sin (I));
return z;
}
Complex cosh (const Complex& a)
{ /* z = cosh(a) */
double R = a.real(), I = a.image();
Complex z;
z.set( cosh (R) * cos (I), sinh (R) * sin (I));
return z;
}
Complex tanh (const Complex& a)
{ /* z = tanh(a) */
double R = a.real(), I = a.image();
Complex z;
if (fabs(R) < 1.0)
{
double D = pow (cos (I), 2.0) + pow (sinh (R), 2.0);
z.set( sinh (R) * cosh (R) / D, 0.5 * sin (2 * I) / D);
}
else
{
double D = pow (cos (I), 2.0) + pow (sinh (R), 2.0);
double F = 1 + pow (cos (I) / sinh (R), 2.0);
z.set( 1.0 / (tanh (R) * F), 0.5 * sin (2 * I) / D);
}
return z;
}
Complex sech (const Complex& a)
{ /* z = sech(a) */
Complex z = cosh (a);
return z.inverse();
}
Complex csch (const Complex& a)
{ /* z = csch(a) */
Complex z = sinh (a);
return z.inverse();
}
Complex coth (const Complex& a)
{ /* z = coth(a) */
Complex z = tanh (a);
return z.inverse();
}
/**********************************************************************
* Inverse Complex Hyperbolic Functions
**********************************************************************/
Complex arcsinh (const Complex& a)
{ /* z = arcsinh(a) */
Complex z = a * Complex(0, 1.0);
z = arcsin (z);
z *= Complex(0, -1);
return z;
}
Complex arccosh (const Complex& a)
{ /* z = arccosh(a) */
Complex z = arccos (a);
if(z.image() > 0)
{
z *= Complex(0, -1);
}
else
{
z *= Complex(0, 1);
}
return z;
}
Complex arccosh (double a)
{ /* z = arccosh(a) */
Complex z;
if (a >= 1)
{
z.set( acosh (a), 0);
}
else
{
if (a >= -1.0)
{
z.set( 0, acos (a));
}
else
{
z.set( acosh (-a), M_PI);
}
}
return z;
}
Complex arctanh (const Complex& a)
{ /* z = arctanh(a) */
if (a.image() == 0.0)
{
return arctanh (a.real());
}
else
{
Complex z = a * Complex(0, 1.0);
z = arctan (z);
z = z * Complex(0, -1.0);
return z;
}
}
Complex arctanh_real (double a)
{ /* z = arctanh(a) */
Complex z;
if (a > -1.0 && a < 1.0)
{
z.set( atanh (a), 0);
}
else
{
z.set( atanh (1 / a), (a < 0) ? M_PI_2 : -M_PI_2);
}
return z;
}
Complex arcsech (const Complex& a)
{ /* z = arcsech(a); */
Complex t = a.inverse();
return arccosh (t);
}
Complex arccsch (const Complex& a)
{ /* z = arccsch(a) */
Complex t = a.inverse();
return arcsinh (t);
}
Complex arccoth (const Complex& a)
{ /* z = arccoth(a) */
Complex t = a.inverse();
return arctanh (t);
}
double acosh (const double x);
double atanh (const double x);
double asinh (const double x);
double log1p (const double x);
#define GSL_SQRT_DBL_EPSILON 1.4901161193847656e-08
#define GSL_DBL_EPSILON 2.2204460492503131e-16
#ifndef M_LN2
#define M_LN2 0.69314718055994530941723212146 /* ln(2) */
#endif
inline double fdiv(double a, double b)
{
return a / b;
}
inline double nan (void)
{
return fdiv (0.0, 0.0);
}
inline double posinf (void)
{
return fdiv (+1.0, 0.0);
}
inline double neginf (void)
{
return fdiv (-1.0, 0.0);
}
double log1p (const double x)
{
volatile double y, z;
y = 1 + x;
z = y - 1;
return log(y) - (z - x) / y ; /* cancels errors with IEEE arithmetic */
}
double acosh (const double x)
{
if (x > 1.0 / GSL_SQRT_DBL_EPSILON)
{
return log (x) + M_LN2;
}
else if (x > 2)
{
return log (2 * x - 1 / (sqrt (x * x - 1) + x));
}
else if (x > 1)
{
double t = x - 1;
return log1p (t + sqrt (2 * t + t * t));
}
else if (x == 1)
{
return 0;
}
else
{
return nan();
}
}
double asinh (const double x)
{
double a = fabs (x);
double s = (x < 0) ? -1 : 1;
if (a > 1 / GSL_SQRT_DBL_EPSILON)
{
return s * (log (a) + M_LN2);
}
else if (a > 2)
{
return s * log (2 * a + 1 / (a + sqrt (a * a + 1)));
}
else if (a > GSL_SQRT_DBL_EPSILON)
{
double a2 = a * a;
return s * log1p (a + a2 / (1 + sqrt (1 + a2)));
}
else
{
return x;
}
}
double atanh (const double x)
{
double a = fabs (x);
double s = (x < 0) ? -1 : 1;
if (a > 1)
{
return nan();
}
else if (a == 1)
{
return (x < 0) ? neginf() : posinf();
}
else if (a >= 0.5)
{
return s * 0.5 * log1p (2 * a / (1 - a));
}
else if (a > GSL_DBL_EPSILON)
{
return s * 0.5 * log1p (2 * a + 2 * a * a / (1 - a));
}
else
{
return x;
}
}
#include <iostream>
#include "complex.h"
using namespace std;
int main()
{
Complex z(1, 2);
cout << z << endl;
cout << z.conjugate() << endl;
cout << -z << endl;
cout << z + Complex(3, 4) << endl;
cout << z - Complex(3, 4) << endl;
cout << z * Complex(3, 4) << endl;
cout << z / Complex(3, 4) << endl;
z = Complex(3, 4);
cout << z << endl;
cout << z.inverse() << endl;
cout << "Hello World!" << endl;
cout << sqrt(Complex(3, 4)) << endl;
cout << exp(Complex(3, 4)) << endl;
cout << pow(Complex(3, 4), Complex(1, 2)) << endl;
cout << pow(Complex(3, 4), 6) << endl;
cout << log(Complex(3, 4), 6) << endl;
cout << sin(Complex(3, 4)) << endl;
cout << arcsin(Complex(3, 4)) << endl;
cout << polar(1, 3.14159265358979 / 4) << endl;
cout << arcsinh(Complex(3, 4)) << endl;
cout << arccosh(Complex(3, 4)) << endl;
cout << arctanh(Complex(3, 4)) << endl;
cout << arcsech(Complex(3, 4)) << endl;
z = 2;
cout << z << endl;
return 0;
}
至此,这个复数类就算是基本完成了。