在C++中如何获得**幂运算符
watermouthhang · · 科技·工程
前言
学 Python 时,我们认识了一个运算符 **,其可以计算次幂。
我们想要将其迁移过来。
构建
不妨定义一个数类,我们希望其可以有正常的四则运算和指幂运算符操作,且有 C++ 风格输入输出。
也就是说,我们希望下面这一段程序正确运行
int main()
{
Num A,B;
std::cin>>A>>B;
std::cout<<A+B<<' '<<A-B<<' '<<A*B<<' '<<A/B<<' '<<A**B<<std::endl;
return 0;
}
写出接口
class Num
{
ll num;
public:
Num(ll n=0ll):num(n){}
TT operator*(){return num;}
friend Num operator*(Num,Num);
friend Num operator-(Num,Num);
friend Num operator+(Num,Num);
friend Num operator/(Num,Num);
friend Num operator-(Num);
friend Num operator**(Num,Num);//?
friend Num ksm(Num,Num);
friend std::ostream& operator<<(std::ostream&,Num);
friend std::istream& operator>>(std::istream&,Num&);
};
CE 了!
C++ 重载运算符必须是已有的运算符,而 C++ 自身没有该运算符。
就要这么放弃了么……
停!我们可以这么做
#include <iostream>
typedef long long ll;
class Num;
class TT
{
ll num;
public:
explicit TT(ll n=0ll):num(n){}
friend Num operator*(Num,TT);
};
class Num
{
ll num;
public:
Num(ll n=0ll):num(n){}
TT operator*(){return (TT)num;}
friend Num operator*(Num,Num);
friend Num operator-(Num,Num);
friend Num operator+(Num,Num);
friend Num operator/(Num,Num);
friend Num operator-(Num);
friend Num operator*(Num,TT);
friend Num ksm(Num,Num);
friend std::ostream& operator<<(std::ostream&,Num);
friend std::istream& operator>>(std::istream&,Num&);
};
我们让 C++ 将 A**B 识别成 A*(*B),这样两个运算符都是已有的。
运行一下?
#include <iostream>
typedef long long ll;
class Num;
class TT
{
ll num;
public:
explicit TT(ll n=0ll):num(n){}
friend Num operator*(Num,TT);
};
class Num
{
ll num;
public:
Num(ll n=0ll):num(n){}
TT operator*(){return (TT)num;}
friend Num operator*(Num,Num);
friend Num operator-(Num,Num);
friend Num operator+(Num,Num);
friend Num operator/(Num,Num);
friend Num operator-(Num);
friend Num operator*(Num,TT);
friend Num ksm(Num,Num);
friend std::ostream& operator<<(std::ostream&,Num);
friend std::istream& operator>>(std::istream&,Num&);
};
Num operator*(Num A,Num B)
{
return A.num*B.num;
}
Num operator+(Num A,Num B)
{
return A.num+B.num;
}
Num operator-(Num A,Num B)
{
return A.num-B.num;
}
Num ksm(Num A,Num B)
{
ll r=1ll;
ll a=A.num,b=B.num;
while(b)
{
if(b&1)r=r*a;
a=a*a;
b>>=1;
}
return r;
}
Num operator-(Num A)
{
return -A.num;
}
Num operator/(Num A,Num B)
{
return A.num/B.num;
}
Num operator*(Num A,TT B)
{
return ksm(A,B.num);
}
std::ostream& operator<<(std::ostream& out,Num x)
{
out<<x.num;
return out;
}
std::istream& operator>>(std::istream& in,Num& x)
{
in>>x.num;
return in;
}
int main()
{
Num A,B;
std::cin>>A>>B;
std::cout<<A+B<<' '<<A-B<<' '<<A*B<<' '<<A/B<<' '<<A**B<<std::endl;
return 0;
}
输入 4 2,输出 6 2 8 2 16。
正确!
左结合?右结合?
cout<<(Num)2**(Num)2**(Num)3 的输出是什么呢?
按照 python,应该是
我们需要维护一个右结合。
可以额外维护一个类 UU,记录整个序列,然后隐式转换时从右向左计算。
#include <iostream>
#include <vector>
typedef long long ll;
class Num;
class TT;
Num ksm(Num,Num);
class UU
{
std::vector<Num> sz;
public:
UU():sz(std::vector<Num>()){}
operator Num();
UU& operator*(TT);
friend UU operator*(Num,TT);
};
class TT
{
ll num;
public:
explicit TT(ll n=0ll):num(n){}
friend UU operator*(Num,TT);
friend UU& UU::operator*(TT);
};
class Num
{
ll num;
public:
Num(ll n=0ll):num(n){}
TT operator*()const{return (TT)num;}
friend Num operator*(Num,Num);
friend Num operator-(Num,Num);
friend Num operator+(Num,Num);
friend Num operator/(Num,Num);
friend Num operator-(Num);
friend UU operator*(Num,TT);
friend Num ksm(Num,Num);
friend std::ostream& operator<<(std::ostream&,Num);
friend std::istream& operator>>(std::istream&,Num&);
};
UU::operator Num()
{
if(!sz.size())return 1ll;
while(sz.size()>1)
{
Num b=*sz.rbegin();
sz.pop_back();
Num a=*sz.rbegin();
sz.pop_back();
sz.push_back(ksm(a,b));
}
return *sz.begin();
}
UU& UU::operator*(TT x)
{
sz.push_back(x.num);
return *this;
}
Num operator*(Num A,Num B)
{
return A.num*B.num;
}
Num operator+(Num A,Num B)
{
return (A.num+B.num);
}
Num operator-(Num A,Num B)
{
return A.num-B.num;
}
Num ksm(Num A,Num B)
{
ll r=1ll;
ll a=A.num,b=B.num;
while(b)
{
if(b&1)r=r*a;
a=a*a;
b>>=1;
}
return r;
}
Num operator-(Num A)
{
return -A.num;
}
Num operator/(Num A,Num B)
{
return A.num/B.num;
}
UU operator*(Num A,TT B)
{
UU R;
R.sz.push_back(A);
R.sz.push_back(B.num);
return R;
}
std::ostream& operator<<(std::ostream& out,Num x)
{
out<<x.num;
return out;
}
std::istream& operator>>(std::istream& in,Num& x)
{
in>>x.num;
return in;
}
int main()
{
Num A,B,C;
std::cin>>A>>B>>C;
std::cout<<A**B**C<<std::endl;
return 0;
}
现在,输出为正确的 256。