lucas52877 2021-04-22 11:49 采纳率: 0%
浏览 51

128位的构造,哪位大佬给我解释一下

#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;
}

  • 写回答

6条回答 默认 最新

  • 快乐鹦鹉 2021-04-22 12:03
    关注

    摸不着头脑啊,这样解释什么呢?

    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器