手写压位高精度(N^2)乘法

O(N)加法
没什么出众的地方,只是一次作业,也当练习一下。


#include<bits/stdc++.h>

// by.dayi 23.5.10
// 第一次尝试写压位高精度
// 其实python可太容易了,但是想趁着机会练一下手写

const int maxn = 10086; // 数组长度,高精度最大可以存4*maxn位,可以无限增加,但是乘法是n^2实现的
const int power = 4; //10^4次方,高精度压位,每个位存4位,因为10^8<2^31,但是10^10>2^31
const int base  = 1e4; // 基数

//最大值 最小值
template <typename T> T max(T a,T b){return a>b?a:b;} 
template <typename T> T min(T a,T b){return a<b?a:b;} 

struct big_dec{//高精度
  int a[maxn];//数组长度
  int _len_big_dec;//当前长度
  int f;

  big_dec(){//结构体构造函数,初始化
    memset(a,0,sizeof(a));
    _len_big_dec = 0;
    f = 0;//f=1为负数
  }

  //从字符串读取
  inline void read_from_str(const char *str){
    int len = strlen(str);//数组长度
    int k = 1;//当前的位置
    int w = 1;//当前位的权值
    int end = 0;//结束位置

    //负数
    if(str[0]=='-'){f=1;end=1;}

    for(int i=len-1;i>=end;i--){
      // 12   345678
      // a[2] a[1]
      a[k] += (str[i]-'0')*w;//加位
      w*=10;//权值增加
      if(w==base){//权值到达基数
        w = 1;//权值归1
        k++;//位置增加
      }
    }
    _len_big_dec = k;
  }
  
  bool is_zero() const { //是否是0
    return _len_big_dec == 1 && a[1] == 0;
  }

  big_dec abs() const { //绝对值
    big_dec ans = *this;
    ans.f = 0;
    return ans;
  }

  //stdout标准输出
  inline void print_stdout(){
    if(this->f)printf("-");//负数
    for(int i=_len_big_dec;i>=1;i--){
      if(i==_len_big_dec && a[i]!=0) printf("%d",a[i]);
      else printf("%04d",a[i]);
    }
  }

  //赋值,也是复制
  big_dec operator = (const big_dec &b){
    _len_big_dec = b._len_big_dec;
    f = b.f;
    for(int i=1;i<=_len_big_dec;i++){
      a[i] = b.a[i];
    }
    return *this;
  }

  // 小于号
  bool operator<(const big_dec &b) const {
    if (f != b.f) {return f > b.f;} //0为正数,1为负数,0>1 
    if (_len_big_dec != b._len_big_dec) {//长度
      return f?(_len_big_dec > b._len_big_dec):(_len_big_dec < b._len_big_dec);
    }

    //长度相同,判断每一位
    for (int i=_len_big_dec;i>=1;i--){
      if (a[i]!=b.a[i]) {
        return f?(a[i]>b.a[i]):(a[i]<b.a[i]);
      }
    }
    return false; // 相等
  }

  // 大于号
  bool operator>(const big_dec &b) const {
    return b<*this; // 反向比较即可
  }


  //加法,要命
  big_dec operator + (const big_dec &b){
    big_dec ans;//结果
    if(f==b.f){//同号相加
      ans.f=b.f;
      int len=max(_len_big_dec,b._len_big_dec);
      for(int i=1;i<=len;++i){
        ans.a[i] += a[i]+b.a[i]; //加位
        if(ans.a[i]>=base){//需要进位
          ans.a[i+1]++;//进位
          ans.a[i]-=base;
        }
      }
      ans._len_big_dec=ans.a[len+1]?len+1:len+0; //判断最高位是否需要进位
    }else{//异号的情况
      big_dec c,d; // c的绝对值小于d
      c = min(this->abs(),b.abs());
      d = max(this->abs(),b.abs());
      ans.f = d.f;//结果与绝对值大的相同
      int len = max(c._len_big_dec,d._len_big_dec);
      for(int i=1;i<=len;++i){
        //如果当前位小于等于c的长度,就减去c的当前位,否则减去0
        ans.a[i] += d.a[i]-(i<=c._len_big_dec?c.a[i]:0);
        if(ans.a[i] < 0){// 需要借位
          ans.a[i] += base; // 加上基数
          ans.a[i+1]--; // 借位
        }
      }
      while(len>1 &&(ans.a[len] == 0)) len--;//去除前导0
      ans._len_big_dec = len;//更新
    }
    return ans;
  }

  //乘法(On^2)
  big_dec operator * (const big_dec &b){
    big_dec ans;
    ans.f = f^b.f;//异或就可以,一样的是正也就是0,不一样的是负也就是1
    for(int i=1;i<=_len_big_dec;++i){
      for(int j=1;j<=b._len_big_dec;++j){
        ans.a[i+j-1] += a[i]*b.a[j];//乘
        if(ans.a[i+j-1]>=base){//需要进位
          ans.a[i+j] += ans.a[i+j-1]/base;//要除基本的倍数
          ans.a[i+j-1] %= base;//mod一下
        }
      }
    }
    int max_len = _len_big_dec+b._len_big_dec;//最大的可能位数
    while(max_len>1 && ans.a[max_len]==0) max_len--;//同样的去除前导0
    ans._len_big_dec = max_len;//赋值
    return ans;
  }

  //相反数
  big_dec operator-() const {
    big_dec ret = *this;
    ret.f = !f; // 符号取反
    return ret;
  }

  //减法,直接加相反数
  big_dec operator - (const big_dec &b){
    big_dec ans ; 
    ans = *this + -b;
    if(*this<b){
      ans.f = !ans.f;
    }
    return ans;
  }

  // to_int
  int to_int() const {
    int ans = 0;
    for (int i=_len_big_dec;i>=1;--i) {
      ans = ans*base+a[i];
    }
    return f ? -ans : ans;
  }
  // to_long_long
  long long to_long_long() const {
    long long ans = 0;
    for (int i=_len_big_dec;i>=1;--i) {
      ans = ans*base+a[i];
    }
    return f ? -ans : ans;
  }
} ;

int main(){
  big_dec a, b, ans;
  char str[10086];

  printf("a:");
  scanf("%s", str);
  a.read_from_str(str);

  printf("b:");
  scanf("%s", str);
  b.read_from_str(str);

  printf("Big Decimal value:\n"); //高精度十进制数值
  printf("a:");a.print_stdout();printf("\n");//输出
  printf("b:");b.print_stdout();printf("\n");//输出

  printf("To int and long long,maybe overflow:\n");//转换为int和long long,可能会溢出
  printf("a_to_int: %d\n", a.to_int());//转换为int
  printf("a_to_long_long: %lld\n", a.to_long_long());//转换为long long
  printf("\n");
  printf("b_to_int: %d\n", b.to_int());//转换为int
  printf("b_to_long_long: %lld\n", b.to_long_long());//转换为long long
  printf("\n");

  ans = a + b;
  printf("a + b = ");//加法
  ans.print_stdout(); printf("\n");

  ans = a - b;
  printf("a - b = ");//减法
  ans.print_stdout(); printf("\n");

  ans = a * b;
  printf("a * b = ");//乘法
  ans.print_stdout(); printf("\n");
 

  return 0;
}

//测试样例1:
//114514
//1919810

//a:114514
//b:1919810
//Big Decimal value:
//a:114514
//b:1919810

//To int and long long,maybe overflow:
//a_to_int: 114514
//a_to_long_long: 114514
//
//b_to_int: 1919810
//b_to_long_long: 1919810
//
//a + b = 2034324
//a - b = -1805296
//a * b = 219845122340


//=========================================
//测试样例2:
//1145140000114514000
//-191981000019198100019198101919810

//输出:
// a:1145140000114514000
// b:-191981000019198100019198101919810
// Big Decimal value:
// a:1145140000114514000
// b:-191981000019198100019198101919810

// To int and long long,maybe overflow:
// a_to_int: 1290442832
// a_to_long_long: 1145140000114514000 (这里正确转换了,还没有溢出longlong)
// 
// b_to_int: -181246018
// b_to_long_long: 5304828336058558398
// 
// a + b = 191981000019196954879197987405810
// a - b = 191981000019199245159198216433810
// a * b = -219845122383969024492182965658049674843245122340000

//py3.11输出结果:-219845122383969024492182965658049674843245122340000
最后修改:2023 年 05 月 10 日
如果觉得我的文章对你有用,请随意赞赏