高精度

高精度

数字的读入

读入字符串时,数字最高位在字符串首(下标小的位置)。但是习惯上,下标最小的位置存放的是数字的 最低位,即存储反转的字符串。

void clear(int a[]) {
  for (int i = 0; i < LEN; ++i) a[i] = 0;
}

void read(int a[]) {
  static char s[LEN + 1];
  cin>>s;
  clear(a);
  int len = s.size();
  // 如上所述,反转
  for (int i = 0; i < len; ++i) 
      a[len - i - 1] = s[i] - '0';
  // s[i] - '0' 就是 s[i] 所表示的数码
}

加法

模拟竖式加法的过程

image-20230721094046732

int a[1001],b[1001],c[1001];
//分别表示被加数,加数,和;
void add(int a[],int b[],int c[])
{
    clear(c);
    for(int i=0;i<len+1;i++)//len表示最大位数
    {
        c[i]+=a[i]+b[i];
        if(c[i]>=10)
        {
            c[i+1]+=1;
            c[i]-=10;
        }
    }
}

减法

模拟竖式减法

image-20230721094119402

int a[1001],b[1001],c[1001];
//分别表示被减数,减数,差
void sub(int a[],int b[],int c[])
{
    clear(c);
    for(int i=0;i<len+1;i++)//len表示最大位数
    {
        c[i]+=a[i]-b[i];
        if(c[i]<=0)
        {
            c[i+1]-=1;
            c[i]+=10;
        }
    }
}

乘法

竖式乘法

int a[1001],b[1001],c[1001];
//分别表示被乘数,乘数,积
void mul(int a[],int b[],int c[])
{
    clear(c);
    for(int i=0;i<=LEN-1;i++)
    {
// 这里直接计算结果中的从低到高第 i 位,且一并处理了进位
// 第 i 次循环为 c[i] 加上了所有满足 p + q = i 的 a[p] 与 b[q] 的乘积之和
// 这样做的效果和直接进行上图的运算最后求和是一样的,只是更加简短的一种实现方式
        for(int j=0;j<=i;j++)
            c[i]+=a[i]*b[i-j];
        if(c[i]>=10)
        {
            c[i+1]=c[i]/10;
            c[i]%=10;
        }
    }
}

除法

// 被除数 a 以下标 last_dg 为最低位,是否可以再减去除数 b 而保持非负
// len 是除数 b 的长度,避免反复计算
bool greater_eq(int a[], int b[], int last_dg, int len) {
  // 有可能被除数剩余的部分比除数长,这个情况下最多多出 1 位,故如此判断即可
  if (a[last_dg + len] != 0) return true;
  // 从高位到低位,逐位比较
  for (int i = len - 1; i >= 0; --i) {
    if (a[last_dg + i] > b[i]) return true;
    if (a[last_dg + i] < b[i]) return false;
  }
  // 相等的情形下也是可行的
  return true;
}

void div(int a[], int b[], int c[], int d[]) {
  clear(c);
  clear(d);
    
  int la, lb;
  for (la = LEN - 1; la > 0; --la)
    if (a[la - 1] != 0) break;
  for (lb = LEN - 1; lb > 0; --lb)
    if (b[lb - 1] != 0) break;
  if (lb == 0) {
    puts("> <");
    return;
  }  // 除数不能为零

  // c 是商
  // d 是被除数的剩余部分,算法结束后自然成为余数
  for (int i = 0; i < la; ++i) d[i] = a[i];
  for (int i = la - lb; i >= 0; --i) {
    // 计算商的第 i 位
    while (greater_eq(d, b, i, lb)) {
      // 若可以减,则减
      // 这一段是一个高精度减法
      for (int j = 0; j < lb; ++j) {
        d[i + j] -= b[j];
        if (d[i + j] < 0) {
          d[i + j + 1] -= 1;
          d[i + j] += 10;
        }
      }
      // 使商的这一位增加 1
      c[i] += 1;
      // 返回循环开头,重新检查
    }
  }
}
posted @ 2025-07-07 15:39  星空丶star  阅读(9)  评论(0)    收藏  举报