#include <iostream>
#include <string>
using namespace std;
/* for 2021's 03,04*/
typedef unsigned long long halfType; //定义存储高位或地位的类型 :半的类型
class tysrxwUINT128
{
public:
//构造函数
tysrxwUINT128(const halfType &h,const halfType &l);
tysrxwUINT128(const halfType &l);
tysrxwUINT128();
//以下都是友元
friend void constructor(tysrxwUINT128 &u,const halfType &l);
friend void constructor(tysrxwUINT128 &u,const halfType & h,const halfType &l);
friend tysrxwUINT128 bitMoveLeft(const tysrxwUINT128 &u,unsigned int n);//u向左移动n个二进制位
friend void output (const tysrxwUINT128& u,unsigned int base);
friend string toString( const string & u,unsigned int base);
friend tysrxwUINT128 add( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //加法 u1+u2
friend tysrxwUINT128 sub( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //减法 u1-u2
friend tysrxwUINT128 mul( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //乘法 u1*u2
friend tysrxwUINT128 div( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //除法 u1/u2
friend tysrxwUINT128 mod( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //余数 u1/u2
friend tysrxwUINT128 pow( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //幂 u1^u2
friend tysrxwUINT128 bitMoveRight(const tysrxwUINT128 &u,unsigned int n);
friend tysrxwUINT128 fromString(const string & s,unsigned int base);
friend tysrxwUINT128 bitAnd(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2);
friend tysrxwUINT128 bitXOr(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2);
friend tysrxwUINT128 bitOr(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2);
friend tysrxwUINT128 bitComplement(const tysrxwUINT128 &u);
friend bool tysrxw_less(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2);
private:
halfType high;
halfType low;
};
tysrxwUINT128 bitMoveLeft(const tysrxwUINT128 &u,unsigned int n);//u向左移动n个二进制位
void output (const tysrxwUINT128& u,unsigned int base=10);
string toString( const string & u,unsigned int base=10);
tysrxwUINT128 add( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //加法 u1+u2
tysrxwUINT128 sub( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //减法 u1-u2
tysrxwUINT128 mul( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //乘法 u1*u2
tysrxwUINT128 div( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //除法 u1/u2
tysrxwUINT128 mod( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //余数 u1/u2
tysrxwUINT128 pow( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //幂 u1^u2
tysrxwUINT128 bitMoveLeft(const tysrxwUINT128 &u,unsigned int n);
tysrxwUINT128 fromString(const string & s,unsigned int base=10);
int main(int argc, char** argv)
{
tysrxwUINT128 bitMoveRight(const tysrxwUINT128 &u,unsigned int n);//u向右移动n个二进制位
tysrxwUINT128 u1=fromString("0xabcedfabcdefabcdefabcdefabcdefabcv"),u2=fromString("02342424123424454");
output(u1,16);
output(u2,8);
return 0;
}
tysrxwUINT128::tysrxwUINT128(const halfType & h,const halfType &l):high(h),low(l)
{}
tysrxwUINT128::tysrxwUINT128(const halfType & l):high(0),low(l)
{}
tysrxwUINT128::tysrxwUINT128():high(0),low(0)
{}
tysrxwUINT128 fromString(const string & s,unsigned int base)
{
tysrxwUINT128 r;
constructor(r,0,0);
int len=s.length();
int pos=0;
if (len>1) //2位及以上才有有前缀的可能。 有前缀,就修改base
{
if(s[0]=='0'&&(s[1]=='x'||s[1]=='X')) base=16,pos=2; //pos移动到真正是数字的位置 ,过滤前缀
else if(s[0]=='0'&&(s[1]=='b'||s[1]=='B')) base=2,pos=2;
else if(s[0]=='0') base=8,pos=1;
}
//偷懒式:
tysrxwUINT128 base128;
constructor(base128,0,base);//把base变成为128类型的数据
for(;pos<len;pos++)
{
tysrxwUINT128 u,base;
int d;
if('A'<=s[pos]&&s[pos]<='F')
d=s[pos]-'A'+10;
else if('a'<=s[pos]&&s[pos]<='f')
d=s[pos]-'a'+10;
else
d=s[pos]-'0';
constructor(u,0,d);
r=add(mul(r,base128),u);
}
return r;
}
//u1/u2
tysrxwUINT128 div( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
//思路:模拟二进制的除法,
// 100101 除11 被除数dividend,除数divisor,商为Q,
// -) 110000 首先把11左移动到被除数最高位 Q=0
// 得 100101 被除数小于除数。 除数都右移1位 Q左移1位+0 Q:0
// -) 11000
// 得 1101 大于等于,则被除数减去除数; Q左移1位+1 Q:1
// -) 1100
// 得: 1 大于等于,则被除数减去除数; Q左移1位+1 Q:11
// -) 110
// 得: 1 大于等于,则被除数减去除数; Q左移1位+1 Q:110
// -) 11
// 得: 1 大于等于,则被除数减去除数; Q左移1位+1 Q:1100
bool tysrxw_less(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //<
bool tysrxw_greater(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //>
bool tysrxw_greater_equal(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //>=
tysrxwUINT128 bitMoveLeft(const tysrxwUINT128 &u,unsigned int n); //<<
tysrxwUINT128 bitMoveRight(const tysrxwUINT128 &u,unsigned int n);// >> 位右移
tysrxwUINT128 increment(tysrxwUINT128 &ps);//++
if (u2.high==0&&u2.low==0) throw("除数为0,溢出!");
tysrxwUINT128 dividend //被除数
, divisor //除数
,quotient//商
,temp
,enDivisor;
dividend=u1,divisor=u2;
constructor(quotient,0,0);//商设置为0
enDivisor=divisor;//初始待减的等于除数
//移动除数,使得除数和被除数的最高位1是一样的。或者低1位
while(true)
{
temp=bitMoveLeft(enDivisor,1);
if (tysrxw_greater(temp,dividend)) //移动1位后,temp大于被除数了,左移结束
break;
if (tysrxw_less(temp,enDivisor))//temp小于除数,这说明divisor最高位是1,因为左移溢出了。 可以结束了
break;
enDivisor=temp;
}
while(tysrxw_greater_equal(enDivisor,divisor)) //enDivisor>=divisor 否则不能再移动了。
{
quotient=bitMoveLeft(quotient,1);//商左移1位
if (tysrxw_greater_equal(dividend,enDivisor))
{
increment(quotient);//quotient+=1 自加1
dividend=sub(dividend,enDivisor);//减去en除数。
}
enDivisor=bitMoveRight(enDivisor,1);
}
return quotient;
}
tysrxwUINT128 mod( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
bool tysrxw_less(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //<
bool tysrxw_greater(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //>
bool tysrxw_greater_equal(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //>=
tysrxwUINT128 bitMoveLeft(const tysrxwUINT128 &u,unsigned int n); //<<
tysrxwUINT128 bitMoveRight(const tysrxwUINT128 &u,unsigned int n);// >> 位右移
tysrxwUINT128 increment(tysrxwUINT128 &ps);//++
if (u2.high==0&&u2.low==0) throw("除数为0,溢出!");
tysrxwUINT128 dividend //被除数
, divisor //除数
,quotient//商
,temp
,enDivisor;
dividend=u1,divisor=u2;
constructor(quotient,0,0);//商设置为0
enDivisor=divisor;//初始待减的等于除数
//移动除数,使得除数和被除数的最高位1是一样的。或者低1位
while(true)
{
temp=bitMoveLeft(enDivisor,1);
if (tysrxw_greater(temp,dividend)) //移动1位后,temp大于被除数了,左移结束
break;
if (tysrxw_less(temp,enDivisor))//temp小于除数,这说明divisor最高位是1,因为左移溢出了。 可以结束了
break;
enDivisor=temp;
}
while(tysrxw_greater_equal(enDivisor,divisor)) //enDivisor>=divisor 不能再移动了。
{
quotient=bitMoveLeft(quotient,1);//商左移1位
if (tysrxw_greater_equal(dividend,enDivisor))
{
increment(quotient);//quotient+=1 自加1
dividend=sub(dividend,enDivisor);//减去en除数。
}
enDivisor=bitMoveRight(enDivisor,1);
}
return dividend;
}
//u1*u2
tysrxwUINT128 mul( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
//思路:模拟二进制的乘法,进行乘法运算。
// 1011
// X 101
//-----------
// 1011
// 10110 本行是0,不加
// 101100
//------------
// 以上累加即可。
tysrxwUINT128 add( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2);
tysrxwUINT128 bitMoveRight(const tysrxwUINT128 &u,unsigned int n);
tysrxwUINT128 bitMoveLeft(const tysrxwUINT128 &u,unsigned int n);
tysrxwUINT128 multiplicand //被乘数
,multiplier //乘数
,result;//积
multiplicand=u1,multiplier=u2; //可以通过比较u1和u2的大小,提高程序效率。
constructor(result,0,0);//积初始为0
while(multiplier.high!=0||multiplier.low!=0) //乘数不为0 从右向左遍历每个二进制位
{
if (multiplier.low%2==1) //末位为1
result=add(result,multiplicand);
multiplicand=bitMoveLeft(multiplicand,1);//被乘数*2,即左移动1位
multiplier=bitMoveRight(multiplier,1);//除数/2,即右移1位
}
return result;
}
//u1+u2
tysrxwUINT128 add( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
tysrxwUINT128 r;
r.high=u1.high+u2.high;
r.low=u1.low+u2.low;
if(r.low<u1.low)//越加越小,说明有进位。
r.high++;
return r;
}
//u1-u2
tysrxwUINT128 sub( const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
tysrxwUINT128 r;
r.high=u1.high-u2.high;
r.low=u1.low-u2.low;
if (u1.low<u2.low) r.high--;//低位不够减,自然向高位借1.
return r;
}
//u向左移动n个二进制位
tysrxwUINT128 bitMoveLeft(const tysrxwUINT128 &u,unsigned int n)
{
tysrxwUINT128 result=u;
if(0<n&&n<64)
{
result.high<<=n;
result.high|=(result.low>>(64-n));
result.low<<=n;
}
else if(64<=n && n<128) //low的移动到high,high没有了。低位补0
{
result.high=result.low;
result.high<<=(n-64);
result.low=0;
}
else //if(128<=n) //全部都出去了。
{
result.high=0;
result.low=0;
}
return result;
}
//可以思考可不可以把这两个同名函数,利用默认参数的方式写为一个函数
//此处由原来指针修改为引用格式
void constructor(tysrxwUINT128 &u,const halfType &h,const halfType & l)
{
u.high=h;
u.low=l;
}
//此处由原来指针修改为引用格式 ,l传递给u的地位,高位赋值为0 。
void constructor(tysrxwUINT128 &u,const halfType & l)
{
u.high=0;
u.low=l;
}
//u向右移动n个二进制位
tysrxwUINT128 bitMoveRight(const tysrxwUINT128 &u,unsigned int n)
{
tysrxwUINT128 result=u;
if(0<n&&n<64) //
{
result.low>>=n;
result.low|=(result.high<<(64-n)); //把高位的64-n位取出来放入到地位高64-n位中
result.high>>=n;
}
else if(64<=n && n<128) //high的移动到low,low没有了。
{
result.low=result.high;
result.low>>=(n-64);
result.high=0;
}
else //if(128<=n) //全部都出去了。
{
result.high=0;
result.low=0;
}
return result;
}
//u1和u2位与 高位和地位分别位与即可
tysrxwUINT128 bitAnd(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
tysrxwUINT128 result;
result.high=(u1.high&u2.high);
result.low=(u1.low&u2.low);
return result;
}
//u1和u2位或,高位和地位分别位或即可
tysrxwUINT128 bitOr(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
tysrxwUINT128 result;
result.high=(u1.high|u2.high);
result.low=(u1.low|u2.low);
return result;
}
//u1和u2位异或, 高位和地位分别位异或即可
tysrxwUINT128 bitXOr(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
tysrxwUINT128 result;
result.high=(u1.high^u2.high);
result.low=(u1.low^u2.low);
return result;
}
//u位反,高位和地位分别位反即可
tysrxwUINT128 bitComplement(const tysrxwUINT128 &u)
{
tysrxwUINT128 result;
result.high=~u.high;
result.low=~u.low;
return result;
}
//u1<u2
bool tysrxw_less(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
return u1.high<u2.high
|| u1.high==u2.high&&u1.low<u2.low;
}
//u1<=u2
bool tysrxw_less_equal(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
return !tysrxw_less(u2,u1);
}
//u1==u2
bool tysrxw_equal_to(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
return u1.high==u2.high&&u1.low==u2.low;
}
//u1>u2
bool tysrxw_greater(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
return tysrxw_less(u2,u1);
}
//u1>=u2
bool tysrxw_greater_equal(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
return !tysrxw_less(u1,u2);
}
//u1!=u2
bool tysrxw_not_equal_to(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2)
{
return !tysrxw_equal_to(u1,u2);
}
//++
tysrxwUINT128 increment(tysrxwUINT128 &u)
{
u.low++;
if(u.low==0) u.high++; //0,说明要进位
}
//--
tysrxwUINT128 decrement(tysrxwUINT128 &u)
{
if(u.low==0) u.high--; //不足,高位借1
u.low--;
}
/*本例直接调用toString*/
void output (const tysrxwUINT128& u, unsigned int base)
{
//使用toString函数
string toString( const tysrxwUINT128 & u,unsigned int base=10);
cout<<toString(u,base)<<endl;
}
/*根据base的不同,分别构造*/
string toString( const tysrxwUINT128 & u,unsigned int base=10)
{
//使用的函数
bool tysrxw_equal_to(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2); //==
tysrxwUINT128 bitMoveLeft(const tysrxwUINT128 &u,unsigned int n);//<<
tysrxwUINT128 bitAnd(const tysrxwUINT128 &u1, const tysrxwUINT128 &u2);//&
tysrxwUINT128 bitMoveRight(const tysrxwUINT128 &u,unsigned int n);//>>
string result="";
if(2==base) //测试 位左移动运算
{
tysrxwUINT128 w;
constructor(w,1);//w=1
for(int i=127;i>=0;i--) //从127位遍历到0位
{
tysrxwUINT128 wi=bitMoveLeft(w,i);//把1移动到第i位
tysrxwUINT128 r=bitAnd(u,wi);//位与获得第i位数值
if(tysrxw_equal_to(r,wi)) //r==wi?
result+="1"; //尾部追加1
else
result+="0"; //尾部追加0
}
}
else if(8==base) //测试,位右移运算
{
tysrxwUINT128 t=u;
for(int i=0;i<43;i++) //128/3=42..2
{ //获得最末3位
int d=t.low%8;//仅考虑地位即可。
result.insert(result.begin(),(char)(d+'0'));//把d转换为字符,插入到result的头部
t=bitMoveRight(t,3);//把t向右移动三位,相当于/8
}
}
else if(16==base) //模拟8==base
{
tysrxwUINT128 t=u;
for(int i=0;i<32;i++) //128/4=32
{ //获得最末4位
int d=t.low%16;//仅考虑地位即可。
char ch=(d<10?'0'+d:d+'A'-10) ;
result.insert(result.begin(),ch);//把d转换为字符,插入到result的头部
t=bitMoveRight(t,4);//把t向右移动三位,相当于/16
}
}
else // if(10==base or else)
{
const int size=50;
int w[size]={1};//用数组模拟一个数,此处表示权
int d[size]={0};//用数组模拟一个数,此处表示十进制数
tysrxwUINT128 t=u;
for(int i=0;i<128;i++,t=bitMoveRight(t,1)) //t向右移动一位,依次遍历所有的二进制位 。每移动一位,权w*2
{
if (t.low%2==1) //末位是1
{
int flag=0;
for(int j=0;j<size;j++) //依次把w加入到d中。
{
d[j]+=w[j]+flag;
if(d[j]>=10)
{
flag=1;
d[j]-=10;
}
else
flag=0;
}
}
//令w*=2
int flag=0;
for(int j=0;j<size;j++)
{
w[j]+=w[j]+flag;
if(w[j]>=10){
flag=1;
w[j]-=10;
}
else
flag=0;
}
}
int pos=size-1;
while(pos>0&&d[pos]==0) pos--;
for(;pos>=0;pos--)
result+=(char)('0'+d[pos]);
}
return result;
}