专栏文章

ComplexNumber:功能齐全的手写 Complex

科技·工程参与者 8已保存评论 22

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
22 条
当前快照
1 份
快照标识符
@mlgxt8h2
此快照首次捕获于
2026/02/11 02:31
上周
此快照最后确认于
2026/02/19 01:15
13 小时前
查看原文

前言

这个想法来自于我之前看过的一本书,上面在讲重载操作符的时候用了复数结构体做例子。但是我觉得它的功能还不够多,没有定义除法运算和关于复数的函数,例如 arg。所以我对它进行了改造。
下面是我改造的历程:
  1. 定义除法运算和输入,将输出写成符合数学形式的样子;
  2. 另开头文件,将整个结构体放进去,并重载逻辑运算符、赋值运算符和输入输出操作符;
  3. 定义关于复数的函数,包括 abs、conj、arg、norm、复数幂、复数对数、复三角函数、复双曲三角函数、复反三角函数,改进输入输出;
  4. 用 template 改写,使它支持 float、double、long double 三个类型

代码

也可以在这里查看CPP
//Code by Andy16673328152 uid:1476867
#include <bits/stdc++.h>
using namespace std;
#ifndef COMPLEX_HPP
#define COMPLEX_HPP
string regetni(string a){
        while(a[a.size()-1]=='0'){
            a.erase(a.size()-1,1);
        }
    return a;
}
template <typename T>
struct Complex{
	static_assert(is_same<T,float>::value||is_same<T,double>::value||is_same<T,long double>::value,"T must be 'float','double' or 'long double',not 'int'");
	T re,ur;
	Complex conj(){
		return {re,-ur};
	}
	T real(){
		return re;
	}
	T imag(){
		return ur;
	}
};
//float
template<>
struct Complex<float>{
	float re,ur;
	Complex<float> conj(){
		return {re,-ur};
	}
	float real(){
		return re;
	}
	float imag(){
		return ur;
	}
};
Complex<float> operator+(Complex <float> a,Complex<float> b){
	a.re+=b.re;
	a.ur+=b.ur;
	return a;
}
Complex <float> operator-(Complex <float> a,Complex <float> b){
	a.re-=b.re;
	a.ur-=b.ur;
	return a;
}
Complex <float> operator*(Complex <float> a,Complex <float> b){
	Complex <float> c;
	c.re=a.re*b.re-a.ur*b.ur;
	c.ur=a.re*b.ur+a.ur*b.re;
	return c; 
}
Complex <float> operator /(Complex <float> a,Complex <float> b){
	if(fabs(b.re)<1e-6&&fabs(b.ur)<1e-6){
		throw runtime_error("Division by zero");
	}
    Complex <float> c,d={b.re,-b.ur},f=a*d;
    c.re=f.re/(b.re*b.re+b.ur*b.ur);
    c.ur=f.ur/(b.re*b.re+b.ur*b.ur);
    return c;
}
bool operator ==(Complex <float> a,Complex <float> b){
	return (fabs(a.re-b.re)<1e-6)&&(fabs(a.ur-b.ur)<1e-6);
}
bool operator !=(Complex <float> a,Complex <float> b){
	return !(a==b);
}
void operator +=(Complex <float> &a,Complex <float> b){
	Complex <float> c=a+b;
	a=c;
}
void operator -=(Complex <float> &a,Complex <float> b){
	Complex <float> c=a-b;
	a=c;
}
void operator *=(Complex <float> &a,Complex <float> b){
	Complex <float> c=a*b;
	a=c;
}
void operator /=(Complex <float> &a,Complex <float> b){
	Complex <float> c=a/b;
	a=c;
}
float fabs(Complex <float> a){
	return sqrt(a.re*a.re+a.ur*a.ur);
}
float norm(Complex <float> a){
	return a.re*a.re+a.ur*a.ur;
}
float arg(Complex <float> a){
	return atan2(a.ur,a.re);
}
Complex <float> pow(Complex <float> a,Complex <float> b){
	Complex <float> f;
	float r=fabs(a);
	float theta=arg(a);
	f={pow(r,b.re)*exp(-b.ur*theta)*cos(b.re*theta+b.ur*log(r)),pow(r,b.re)*exp(-b.ur*theta)*sin(b.re*theta+b.ur*log(r))};
	return f;
}
Complex <float> exp(Complex <float> a){
	Complex <float> b={cos(a.ur),sin(a.ur)},d={exp(a.re),0};
	return d*b;
}
Complex <float> log(Complex <float> a){
	return {log(fabs(a)),arg(a)};
}
Complex <float> log10(Complex <float> a){
	Complex <float> b={log(10),0};
	return log(a)/b;
}
Complex <float> log2(Complex <float> a){
	Complex <float> b={log(2),0};
	return log(a)/b;
}
Complex <float> logp(Complex <float> a,Complex <float> b){
	return log(a)/log(b);
}
Complex <float> nthrt(Complex <float> a,Complex <float> b){
	Complex <float> c={1,0};
	return pow(a,c/b);
}
Complex <float> sqrt(Complex <float> a){
	Complex <float> b={2,0};
	return nthrt(a,b);
}
Complex <float> sin(Complex <float> a){
	return {sin(a.re)*cosh(a.ur),cos(a.re)*sinh(a.ur)};
}
Complex <float> cos(Complex <float> a){
    return {cos(a.re)*cosh(a.ur),-sin(a.re)*sinh(a.ur)};
}
Complex <float> tan(Complex <float> a){
    return sin(a)/cos(a);
}
Complex <float> asin(Complex <float> a){
	Complex <float> b={0,-1},c={1,0},d={0,1};
	return b*log(d*a+sqrt(c-a*a));
}
Complex <float> acos(Complex <float> a){
	Complex <float> b={0,-1},c={1,0};
	return b*log(a+sqrt(a*a-c));
}
Complex <float> atan(Complex <float> a){
	Complex <float> b={0,1},c={0,0.5},d={1,0};
	return c*log((d+b*a)/(d-b*a));
}
Complex <float> sinh(Complex <float> a){
	Complex <float> b={-a.re,-a.ur},c={2,0};
	return (exp(a)-exp(b))/c;
}
Complex <float> cosh(Complex <float> a){
	Complex <float> b={-a.re,-a.ur},c={2,0};
	return (exp(a)+exp(b))/c;
}
Complex <float> tanh(Complex <float> a){
	return sinh(a)/cosh(a);
}
istream &operator >>(istream &in,Complex <float> &c){
	string s,s1,s2,r="i",ss="1",d="+0i",f="+",h="-",ze="0",zz="0+";
	in>>s;
	if(s.find(r)==-1){
		s+=d;
	}
	int g=1,dot=0,g1=1;
	if((s.find(r)!=s.size()-1)&&(s.find(r)!=-1)){
		if(s[0]!='-'){
			s="+"+s;
		}
		int k=s.find(r);
		s1=s.substr(0,k+1);
		s2=s.substr(k+1,s.size()-k-1);
		s=s2+s1;
		if(s[0]!='-'){
			s.erase(0,1);
		}
	}
	if(!isdigit(s[s.find(r)-1])){
		s.insert(s.find(r),ss);
	}
	if(s.find("+")==-1){
		if(s.find("-")!=-1){
			s=ze+s;
		}else{
			s=zz+s;
		}
	}
	for(int i=0;i<s.size();){
		if(s[i]=='-'){
			g=-1;
			i++;
		}
		while(s[i]>='0'&&s[i]<='9'){
			c.re=c.re*10+(s[i]-'0');
			i++;
		}
		if(s[i]=='.'){
			dot=i;
			i++;
		}
		
		while(s[i]>='0'&&s[i]<='9'){
			c.re+=(s[i]-'0')*pow(10,-i+dot);
			i++;
		}
		dot=0;
		if(s[i]=='-'){
			g1=-1;
		}
		
		i++;
		if(s[i]=='i'){
			c.ur*=g1;
		}
		while(s[i]>='0'&&s[i]<='9'){
			c.ur=c.ur*10+(s[i]-'0');
			i++;
		}
		if(s[i]=='.'){
			dot=i;
			i++;
		}
		while(s[i]>='0'&&s[i]<='9'){
			c.ur+=(s[i]-'0')*pow(10,-i+dot);
			i++;
		}
	}
	c.re*=g;
	c.ur*=g1;
	return in;
}
ostream &operator <<(ostream &o,const Complex <float> &c){
	string s=to_string(c.re),s1=to_string(c.ur);
	s=regetni(s);
	s1=regetni(s1);
	if(s.find(".")==s.size()-1){
		s.erase(s.size()-1,1);
	}
	if(s1.find(".")==s1.size()-1){
		s1.erase(s1.size()-1,1);
	}
	if(fabs(c.ur-0)<1e-6){
		o<<s;
	}else{
		if(fabs(c.re-0)<1e-6){
			if(fabs(c.ur-1)<1e-6){
				o<<"i";
			}else{
				o<<s1<<"i";
			}
		}else{
			if(fabs(c.ur-1)<1e-6){
				o<<s<<"+"<<"i";
			}else{
				if(fabs(c.ur+1)<1e-6){
					o<<s<<"-i";
				}else{
					if(c.ur<0){
						o<<s<<s1<<"i";
					}else{
						o<<s<<"+"<<s1<<"i";
					}
				}
			}
		}
	}
	return o;
}
//double
template<>
struct Complex<double>{
	double re,ur;
	Complex<double> conj(){
		return {re,-ur};
	}
	double real(){
		return re;
	}
	double imag(){
		return ur;
	}
};
Complex <double> operator+(Complex <double> a,Complex <double> b){
	a.re+=b.re;
	a.ur+=b.ur;
	return a;
}
Complex <double> operator-(Complex <double> a,Complex <double> b){
	a.re-=b.re;
	a.ur-=b.ur;
	return a;
}
Complex <double> operator*(Complex <double> a,Complex <double> b){
	Complex <double> c;
	c.re=a.re*b.re-a.ur*b.ur;
	c.ur=a.re*b.ur+a.ur*b.re;
	return c; 
}
Complex <double> operator /(Complex <double> a,Complex <double> b){
	if(fabs(b.re)<1e-6&&fabs(b.ur)<1e-6){
		throw runtime_error("Division by zero");
	}
    Complex <double> c,d={b.re,-b.ur},f=a*d;
    c.re=f.re/(b.re*b.re+b.ur*b.ur);
    c.ur=f.ur/(b.re*b.re+b.ur*b.ur);
    return c;
}
bool operator ==(Complex <double> a,Complex <double> b){
	return (fabs(a.re-b.re)<1e-6)&&(fabs(a.ur-b.ur)<1e-6);
}
bool operator !=(Complex <double> a,Complex <double> b){
	return !(a==b);
}
void operator +=(Complex <double> &a,Complex <double> b){
	Complex <double> c=a+b;
	a=c;
}
void operator -=(Complex <double> &a,Complex <double> b){
	Complex <double> c=a-b;
	a=c;
}
void operator *=(Complex <double> &a,Complex <double> b){
	Complex <double> c=a*b;
	a=c;
}
void operator /=(Complex <double> &a,Complex <double> b){
	Complex <double> c=a/b;
	a=c;
}
double fabs(Complex <double> a){
	return sqrt(a.re*a.re+a.ur*a.ur);
}
double norm(Complex <double> a){
	return a.re*a.re+a.ur*a.ur;
}
double arg(Complex <double> a){
	return atan2(a.ur,a.re);
}
Complex <double> pow(Complex <double> a,Complex <double> b){
	Complex <double> f;
	double r=fabs(a);
	double theta=arg(a);
	f={pow(r,b.re)*exp(-b.ur*theta)*cos(b.re*theta+b.ur*log(r)),pow(r,b.re)*exp(-b.ur*theta)*sin(b.re*theta+b.ur*log(r))};
	return f;
}
Complex <double> exp(Complex <double> a){
	Complex <double> b={cos(a.ur),sin(a.ur)},d={exp(a.re),0};
	return d*b;
}
Complex <double> log(Complex <double> a){
	return {log(fabs(a)),arg(a)};
}
Complex <double> log10(Complex <double> a){
	Complex <double> b={log(10),0};
	return log(a)/b;
}
Complex <double> log2(Complex <double> a){
	Complex <double> b={log(2),0};
	return log(a)/b;
}
Complex <double> logp(Complex <double> a,Complex <double> b){
	return log(a)/log(b);
}
Complex <double> nthrt(Complex <double> a,Complex <double> b){
	Complex <double> c={1,0};
	return pow(a,c/b);
}
Complex <double> sqrt(Complex <double> a){
	Complex <double> b={2,0};
	return nthrt(a,b);
}
Complex <double> sin(Complex <double> a){
	return {sin(a.re)*cosh(a.ur),cos(a.re)*sinh(a.ur)};
}
Complex <double> cos(Complex <double> a){
    return {cos(a.re)*cosh(a.ur),-sin(a.re)*sinh(a.ur)};
}
Complex <double> tan(Complex <double> a){
    return sin(a)/cos(a);
}
Complex <double> asin(Complex <double> a){
	Complex <double> b={0,-1},c={1,0},d={0,1};
	return b*log(d*a+sqrt(c-a*a));
}
Complex <double> acos(Complex <double> a){
	Complex <double> b={0,-1},c={1,0};
	return b*log(a+sqrt(a*a-c));
}
Complex <double> atan(Complex <double> a){
	Complex <double> b={0,1},c={0,0.5},d={1,0};
	return c*log((d+b*a)/(d-b*a));
}
Complex <double> sinh(Complex <double> a){
	Complex <double> b={-a.re,-a.ur},c={2,0};
	return (exp(a)-exp(b))/c;
}
Complex <double> cosh(Complex <double> a){
	Complex <double> b={-a.re,-a.ur},c={2,0};
	return (exp(a)+exp(b))/c;
}
Complex <double> tanh(Complex <double> a){
	return sinh(a)/cosh(a);
}
istream &operator >>(istream &in,Complex <double> &c){
	string s,s1,s2,r="i",ss="1",d="+0i",f="+",h="-",ze="0",zz="0+";
	in>>s;
	if(s.find(r)==-1){
		s+=d;
	}
	int g=1,dot=0,g1=1;
	if((s.find(r)!=s.size()-1)&&(s.find(r)!=-1)){
		if(s[0]!='-'){
			s="+"+s;
		}
		int k=s.find(r);
		s1=s.substr(0,k+1);
		s2=s.substr(k+1,s.size()-k-1);
		s=s2+s1;
		if(s[0]!='-'){
			s.erase(0,1);
		}
	}
	if(!isdigit(s[s.find(r)-1])){
		s.insert(s.find(r),ss);
	}
	if(s.find("+")==-1){
		if(s.find("-")!=-1){
			s=ze+s;
		}else{
			s=zz+s;
		}
	}
	for(int i=0;i<s.size();){
		if(s[i]=='-'){
			g=-1;
			i++;
		}
		while(s[i]>='0'&&s[i]<='9'){
			c.re=c.re*10+(s[i]-'0');
			i++;
		}
		if(s[i]=='.'){
			dot=i;
			i++;
		}
		
		while(s[i]>='0'&&s[i]<='9'){
			c.re+=(s[i]-'0')*pow(10,-i+dot);
			i++;
		}
		dot=0;
		if(s[i]=='-'){
			g1=-1;
		}
		
		i++;
		if(s[i]=='i'){
			c.ur*=g1;
		}
		while(s[i]>='0'&&s[i]<='9'){
			c.ur=c.ur*10+(s[i]-'0');
			i++;
		}
		if(s[i]=='.'){
			dot=i;
			i++;
		}
		while(s[i]>='0'&&s[i]<='9'){
			c.ur+=(s[i]-'0')*pow(10,-i+dot);
			i++;
		}
	}
	c.re*=g;
	c.ur*=g1;
	return in;
}
ostream &operator <<(ostream &o,const Complex <double> &c){
	string s=to_string(c.re),s1=to_string(c.ur);
	s=regetni(s);
	s1=regetni(s1);
	if(s.find(".")==s.size()-1){
		s.erase(s.size()-1,1);
	}
	if(s1.find(".")==s1.size()-1){
		s1.erase(s1.size()-1,1);
	}
	if(fabs(c.ur-0)<1e-6){
		o<<s;
	}else{
		if(fabs(c.re-0)<1e-6){
			if(fabs(c.ur-1)<1e-6){
				o<<"i";
			}else{
				o<<s1<<"i";
			}
		}else{
			if(fabs(c.ur-1)<1e-6){
				o<<s<<"+"<<"i";
			}else{
				if(fabs(c.ur+1)<1e-6){
					o<<s<<"-i";
				}else{
					if(c.ur<0){
						o<<s<<s1<<"i";
					}else{
						o<<s<<"+"<<s1<<"i";
					}
				}
			}
		}
	}
	return o;
}
//long double
template<>
struct Complex<long double>{
	long double re,ur;
	Complex<long double> conj(){
		return {re,-ur};
	}
	long double real(){
		return re;
	}
	long double imag(){
		return ur;
	}
};
Complex <long double> operator+(Complex <long double> a,Complex <long double> b){
	a.re+=b.re;
	a.ur+=b.ur;
	return a;
}
Complex <long double> operator-(Complex <long double> a,Complex <long double> b){
	a.re-=b.re;
	a.ur-=b.ur;
	return a;
}
Complex <long double> operator*(Complex <long double> a,Complex <long double> b){
	Complex <long double> c;
	c.re=a.re*b.re-a.ur*b.ur;
	c.ur=a.re*b.ur+a.ur*b.re;
	return c; 
}
Complex <long double> operator /(Complex <long double> a,Complex <long double> b){
	if(fabsl(b.re)<1e-6&&fabsl(b.ur)<1e-6){
		throw runtime_error("Division by zero");
	}
    Complex <long double> c,d={b.re,-b.ur},f=a*d;
    c.re=f.re/(b.re*b.re+b.ur*b.ur);
    c.ur=f.ur/(b.re*b.re+b.ur*b.ur);
    return c;
}
bool operator ==(Complex <long double> a,Complex <long double> b){
	return (fabs(a.re-b.re)<1e-6)&&(fabs(a.ur-b.ur)<1e-6);
}
bool operator !=(Complex <long double> a,Complex <long double> b){
	return !(a==b);
}
void operator +=(Complex <long double> &a,Complex <long double> b){
	Complex <long double> c=a+b;
	a=c;
}
void operator -=(Complex <long double> &a,Complex <long double> b){
	Complex <long double> c=a-b;
	a=c;
}
void operator *=(Complex <long double> &a,Complex <long double> b){
	Complex <long double> c=a*b;
	a=c;
}
void operator /=(Complex <long double> &a,Complex <long double> b){
	Complex <long double> c=a/b;
	a=c;
}
long double fabs(Complex <long double> a){
	return sqrt(a.re*a.re+a.ur*a.ur);
}
long double norm(Complex <long double> a){
	return a.re*a.re+a.ur*a.ur;
}
long double arg(Complex <long double> a){
	return atan2(a.ur,a.re);
}
Complex <long double> pow(Complex <long double> a,Complex <long double> b){
	Complex <long double> f;
	long double r=fabs(a);
	long double theta=arg(a);
	f={pow(r,b.re)*exp(-b.ur*theta)*cos(b.re*theta+b.ur*log(r)),pow(r,b.re)*exp(-b.ur*theta)*sin(b.re*theta+b.ur*log(r))};
	return f;
}
Complex <long double> exp(Complex <long double> a){
	Complex <long double> b={cos(a.ur),sin(a.ur)},d={exp(a.re),0};
	return d*b;
}
Complex <long double> log(Complex <long double> a){
	return {log(fabs(a)),arg(a)};
}
Complex <long double> log10(Complex <long double> a){
	Complex <long double> b={log(10),0};
	return log(a)/b;
}
Complex <long double> log2(Complex <long double> a){
	Complex <long double> b={log(2),0};
	return log(a)/b;
}
Complex <long double> logp(Complex <long double> a,Complex <long double> b){
	return log(a)/log(b);
}
Complex <long double> nthrt(Complex <long double> a,Complex <long double> b){
	Complex <long double> c={1,0};
	return pow(a,c/b);
}
Complex <long double> sqrt(Complex <long double> a){
	Complex <long double> b={2,0};
	return nthrt(a,b);
}
Complex <long double> sin(Complex <long double> a){
	return {sin(a.re)*cosh(a.ur),cos(a.re)*sinh(a.ur)};
}
Complex <long double> cos(Complex <long double> a){
    return {cos(a.re)*cosh(a.ur),-sin(a.re)*sinh(a.ur)};
}
Complex <long double> tan(Complex <long double> a){
    return sin(a)/cos(a);
}
Complex <long double> asin(Complex <long double> a){
	Complex <long double> b={0,-1},c={1,0},d={0,1};
	return b*log(d*a+sqrt(c-a*a));
}
Complex <long double> acos(Complex <long double> a){
	Complex <long double> b={0,-1},c={1,0};
	return b*log(a+sqrt(a*a-c));
}
Complex <long double> atan(Complex <long double> a){
	Complex <long double> b={0,1},c={0,0.5},d={1,0};
	return c*log((d+b*a)/(d-b*a));
}
Complex <long double> sinh(Complex <long double> a){
	Complex <long double> b={-a.re,-a.ur},c={2,0};
	return (exp(a)-exp(b))/c;
}
Complex <long double> cosh(Complex <long double> a){
	Complex <long double> b={-a.re,-a.ur},c={2,0};
	return (exp(a)+exp(b))/c;
}
Complex <long double> tanh(Complex <long double> a){
	return sinh(a)/cosh(a);
}
istream &operator >>(istream &in,Complex <long double> &c){
	string s,s1,s2,r="i",ss="1",d="+0i",f="+",h="-",ze="0",zz="0+";
	in>>s;
	if(s.find(r)==-1){
		s+=d;
	}
	int g=1,dot=0,g1=1;
	if((s.find(r)!=s.size()-1)&&(s.find(r)!=-1)){
		if(s[0]!='-'){
			s="+"+s;
		}
		int k=s.find(r);
		s1=s.substr(0,k+1);
		s2=s.substr(k+1,s.size()-k-1);
		s=s2+s1;
		if(s[0]!='-'){
			s.erase(0,1);
		}
	}
	if(!isdigit(s[s.find(r)-1])){
		s.insert(s.find(r),ss);
	}
	if(s.find("+")==-1){
		if(s.find("-")!=-1){
			s=ze+s;
		}else{
			s=zz+s;
		}
	}
	for(int i=0;i<s.size();){
		if(s[i]=='-'){
			g=-1;
			i++;
		}
		while(s[i]>='0'&&s[i]<='9'){
			c.re=c.re*10+(s[i]-'0');
			i++;
		}
		if(s[i]=='.'){
			dot=i;
			i++;
		}
		
		while(s[i]>='0'&&s[i]<='9'){
			c.re+=(s[i]-'0')*pow(10,-i+dot);
			i++;
		}
		dot=0;
		if(s[i]=='-'){
			g1=-1;
		}
		
		i++;
		if(s[i]=='i'){
			c.ur*=g1;
		}
		while(s[i]>='0'&&s[i]<='9'){
			c.ur=c.ur*10+(s[i]-'0');
			i++;
		}
		if(s[i]=='.'){
			dot=i;
			i++;
		}
		while(s[i]>='0'&&s[i]<='9'){
			c.ur+=(s[i]-'0')*pow(10,-i+dot);
			i++;
		}
	}
	c.re*=g;
	c.ur*=g1;
	return in;
}
ostream &operator <<(ostream &o,const Complex <long double> &c){
	string s=to_string(c.re),s1=to_string(c.ur);
	s=regetni(s);
	s1=regetni(s1);
	if(s.find(".")==s.size()-1){
		s.erase(s.size()-1,1);
	}
	if(s1.find(".")==s1.size()-1){
		s1.erase(s1.size()-1,1);
	}
	if(fabs(c.ur-0)<1e-6){
		o<<s;
	}else{
		if(fabs(c.re-0)<1e-6){
			if(fabs(c.ur-1)<1e-6){
				o<<"i";
			}else{
				o<<s1<<"i";
			}
		}else{
			if(fabs(c.ur-1)<1e-6){
				o<<s<<"+"<<"i";
			}else{
				if(fabs(c.ur+1)<1e-6){
					o<<s<<"-i";
				}else{
					if(c.ur<0){
						o<<s<<s1<<"i";
					}else{
						o<<s<<"+"<<s1<<"i";
					}
				}
			}
		}
	}
	return o;
}
#endif/*COMPLEX_HPP*/

Update on 2026/01/26

添加类型约束,当 T 不为浮点数时报错。

Update on 2026/01/27

除法添加除零保护,当除数为零时报 RE。

后记

这是我的第一个项目,如果有建议,欢迎联系我,我会及时改进。

评论

22 条评论,欢迎与作者交流。

正在加载评论...