高精

  这几天做题遇到一些关于高精的题,很烦的!

  一开始是用双long long 强行拼凑的int128,但是有点局限,今天搜集资料自己写了下高精

  个人感觉(我的高精)良好(我是对付用了),就写进博文里,欢迎大家看看,提提意见。

  结构体

1 int len,s[50];//习惯性扔掉位置零ps:位置零其实可以存长度的
2 int128() { memset(s, 0, sizeof(s)); len = 0; }

 

  主要就是数组存储每位的数字,加上长度变量便于计算(没感觉到~//结构体借鉴来的hhh~)(自己需要的构造函数自己加上)

  然后就是一些基本功能的重载

 1 bool operator == (const int128& a, const int128& b) {
 2     if (a.len != b.len)return 0;
 3     for (int i = max(a.len, b.len); i >= 0; --i)
 4         if (a.s[i] != b.s[i])return 0;
 5     return 1;
 6 }
 7 bool operator > (const int128& a, const int128& b) {
 8     if (a.len < b.len)return 0;
 9     for (int i = max(a.len, b.len); i >= 0; --i)
10         if (a.s[i] > b.s[i])return 1;
11         else if (a.s[i] < b.s[i])break;
12     return 0;
13 }
14 bool operator < (const int128& a, const int128& b) {
15     if (a.len > b.len)return 0;
16     for (int i = max(a.len, b.len); i >= 0; --i)
17         if (a.s[i] < b.s[i])return 1;
18         else if (a.s[i] > b.s[i])break;
19     return 0;
20 }
21 bool operator >= (const int128& a, const int128& b) {
22     if (a.len < b.len)return 0;
23     for (int i = max(a.len, b.len); i >= 0; --i)
24         if (a.s[i] < b.s[i])return 0;
25         else if (a.s[i] > b.s[i])break;
26     return 1;
27 }
28 bool operator <= (const int128& a, const int128& b) {
29     if (a.len > b.len)return 0;
30     for (int i = max(a.len, b.len); i >= 0; --i)
31         if (a.s[i] > b.s[i])return 0;
32         else if (a.s[i] < b.s[i])break;
33     return 1;
34 }

 

  然后开始实现基本功能

1.加

int128 operator + (int128 a, int128 b) {
    int128 temp;
    temp.len = max(a.len, b.len);
    for (int i = 1; i <= temp.len; ++i) {
        temp.s[i] += (a.s[i] + b.s[i]);
        if (temp.s[i] >= 10) { temp.s[i] -= 10; temp.s[i + 1] += 1; }//毕竟十进制数单位相加,总不能加出20吧,hhh~
    }
    if (temp.s[temp.len + 1])++temp.len;
    return temp;
}

  直接逐位相加进位就行

2.减

int128 operator - (int128 a, int128 b) {//对于减法,我的思路比较麻烦,就是类似二进制相减//由于懒着写符号我这里无论a>b还是b>a统统大减小
    int128 temp;
    temp.len = max(a.len, b.len);
    b.len = a.len = temp.len;
    if (a < b)//如果a较小,则对a取反
        for (int i = 1; i <= temp.len; ++i) a.s[i] = 9 - a.s[i];
    else//否则对b取反
        for (int i = 1; i <= temp.len; ++i) b.s[i] = 9 - b.s[i];
    temp = a + b + 1;//不要忘记加一???
    temp.len = a.len;
    for (int i = temp.len; i >= 1; --i)//把零位删除
        if (!temp.s[i])temp.len--;
        else break;//遇到第一个非零位即退出
    temp.s[temp.len + 1] = 0;
    return temp;
}

  这里我直接让小的数字取反(十进制取反???(我想出来的???))(就是逐位被9减而已),然后两个数字相加,在加一就可以了(毕竟没有补码~)

3.乘

int128 operator * (int128 a, int128 b) {
    int128 temp;
    if (a == zero || b == zero)return zero;//任意一方为零则返回零
    temp.len = a.len + b.len - 1;//最小位数
    for (int i = 1; i <= a.len; ++i)
        for (int j = 1; j <= b.len; ++j) {
            temp.s[i + j - 1] += a.s[i] * b.s[j];//各个位置相乘进行存储
        }
    for (int i = 1; i <= temp.len; ++i) {
        temp.s[i + 1] += temp.s[i] / 10;//大于个位的部分要前进
        temp.s[i] %= 10;
    }
    if (temp.s[temp.len + 1])++temp.len;//最高位十进制数相乘,总不能乘出三位数吧,hhh~
    return temp;
}

  这个直接模仿正常相乘做的,(借鉴的思路QAQ)个人感觉好妙啊~

4.除

int128 operator / (int128 a, int128 b) {
    int128 temp;
    while (a > b) {
        a = a - b;
        temp = temp + 1;
    }
    return temp;
}

  直接减就可以了

5.输出输入

ostream& operator << (ostream& out, int128 a) {
    for (int i = a.len; i > 0; --i)
        out << a.s[i];
    return out;
}
istream& operator >> (istream& in, int128& a) {
    memset(a.s, 0, sizeof(a.s)); 
    a.len = 0;
    char c[50];
    in >> c;
    while (c[a.len++] != '\0');
    a.len--;
    for (int i = 1; i <= a.len; ++i) {
        a.s[i] = c[a.len - i] - '0';
    }
    return in;
}

 

大功告成!

有错误请留言,感谢大家能看到这篇文章

 

 

 

 

 

 

  

 

posted @ 2018-12-18 20:43  DukeOfYork  阅读(675)  评论(0)    收藏  举报