ComplexNumber:功能齐全的手写 Complex

· · 科技·工程

前言

这个想法来自于我之前看过的一本书,上面在讲重载操作符的时候用了复数结构体做例子。但是我觉得它的功能还不够多,没有定义除法运算和关于复数的函数,例如 arg。所以我对它进行了改造。

下面是我改造的历程:

  1. 定义除法运算和输入,将输出写成符合数学形式的样子;
  2. 另开头文件,将整个结构体放进去,并重载逻辑运算符、赋值运算符和输入输出操作符;
  3. 定义关于复数的函数,包括 abs、conj、arg、norm、复数幂、复数对数、复三角函数、复双曲三角函数、复反三角函数,改进输入输出;
  4. 用 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。

后记

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