ComplexNumber:功能齐全的手写 Complex
Andy16673328152 · · 科技·工程
前言
这个想法来自于我之前看过的一本书,上面在讲重载操作符的时候用了复数结构体做例子。但是我觉得它的功能还不够多,没有定义除法运算和关于复数的函数,例如 arg。所以我对它进行了改造。
下面是我改造的历程:
- 定义除法运算和输入,将输出写成符合数学形式的样子;
- 另开头文件,将整个结构体放进去,并重载逻辑运算符、赋值运算符和输入输出操作符;
- 定义关于复数的函数,包括 abs、conj、arg、norm、复数幂、复数对数、复三角函数、复双曲三角函数、复反三角函数,改进输入输出;
- 用 template 改写,使它支持 float、double、long double 三个类型
代码
点击此链接即可下载
云剪贴板地址:https://www.luogu.com.cn/paste/4cnxxdii
:::info[也可以在这里查看]
//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。
后记
这是我的第一个项目,如果有建议,欢迎联系我,我会及时改进。