zoukankan      html  css  js  c++  java
  • 高进度加法

    a + b 自然是个很简单的问题,但若 a 和 b 都能达到两百位的话,连 unsigned long long 都存不了,这是就要用到高精度加法。

    具体原理就是让电脑模拟列竖式加法。

    首先我们用数组存这两个数。为了方便读入,我们采用字符串读入,然后将其转化成数字存进数组中。存进数组的时候要倒着存入,为什么呢?这样的话就能保证两个数的每一位都对齐了,为接下来的模拟列竖式提供了很大的便利。

    模拟列竖式其实也不必多说,写法也不少。其实关键在于进位的问题,一种写法是先进位,在把这一位的两数相加;一种是先相加,然后为下一位进位。这两种写法是一样的,喜欢哪一种,就看个人习惯吧。

    那么先说一下第一种方法。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    const int maxn = 1e5 + 5;
    char a1[maxn], b1[maxn];
    int a[maxn], b[maxn], c[maxn]; 
    int jinwei = 0;
    int main()
    {
        scanf("%s%s", a1, b1);
        int la = strlen(a1), lb = strlen(b1);
        for(int i = 0; i < la; ++i) a[la - 1 - i] = a1[i] - '0';    //倒着存入 
        for(int i = 0; i < lb; ++i) b[lb - 1 - i] = b1[i] - '0';
        for(int i = 0; i < max(la, lb); ++i)        //当然要加到位数多的数了 
        {
            c[i] = c[i] + jinwei + a[i] + b[i];        
            jinwei = c[i] / 10;
            c[i] %= 10;
        }
        int x = max(la, lb);
        if(jinwei > 0) c[x] += jinwei;        //处理最高位的进位 
        while(x > 0 && c[x] == 0) x--;        //删除前导0,比如 0000 + 00 = 0,而不是 0000 
        for(int i = x; i >= 0; --i) printf("%d", c[i]);        //倒着输出 
        printf("
    ");
        return 0;
    }

    仔细瞅一瞅,这个代码其实还可以优化一下:

    1.不用开 c 数组,在 a 数组上改动即可。

    2.这其实不算什么优化,只不过代码看得更简洁:考虑一下最高位进位的问题,若最高位可以进位,那新的一位一定是超出了 max(la, lb),因此会跳出循环,所以我们的写法就是在循环外面单独处理。但其实我们完全可以把它放到循环里面,只要把最高位的下一位看成一位,而且可以确定的是,这一位一定不会再进位了(因为没有数,默认是0,加任何小于10的数都不会进位),这么一改,我们也就不用考虑最高位进位的事了。

    发一下优化后的

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstring>
     6 using namespace std;
     7 const int maxn = 1e5 + 5;
     8 char a1[maxn], b1[maxn];
     9 int a[maxn], b[maxn]; 
    10 int jinwei = 0;
    11 int main()
    12 {
    13     scanf("%s%s", a1, b1);
    14     int la = strlen(a1), lb = strlen(b1);
    15     for(int i = 0; i < la; ++i) a[la - 1 - i] = a1[i] - '0';     
    16     for(int i = 0; i < lb; ++i) b[lb - 1 - i] = b1[i] - '0';
    17     for(int i = 0; i <= max(la, lb); ++i)    //注意加了个 '=',默认加到最高位的下一位 
    18     {
    19         a[i] = a[i] +jinwei + b[i];    
    20         jinwei = a[i] / 10;
    21         a[i] %= 10;
    22     }
    23     int x = max(la, lb);        //不用考虑最高位进位的事了 
    24     while(x > 0 && a[x] == 0) x--;        //删除前导0
    25     for(int i = x; i >= 0; --i) printf("%d", a[i]);    
    26     printf("
    ");
    27     return 0;
    28 }

    那就顺便说一下第二种方法吧。

    其实差不多,只不过不用开一个变量记录进位了,因为每一次考虑的是给下一位进位,只要 c[i + 1] 处理一下就行了,除此之外,也就没什么差别。

    就直接发优化后的代码了

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstring>
     6 using namespace std;
     7 const int maxn = 1e5 + 5;
     8 char a1[maxn], b1[maxn];
     9 int a[maxn], b[maxn]; 
    10 int main()
    11 {
    12     scanf("%s%s", a1, b1);
    13     int la = strlen(a1), lb = strlen(b1);
    14     for(int i = 0; i < la; ++i) a[la - 1 - i] = a1[i] - '0';     
    15     for(int i = 0; i < lb; ++i) b[lb - 1 - i] = b1[i] - '0';
    16     for(int i = 0; i <= max(la, lb); ++i)    
    17     {
    18         a[i] += b[i];    
    19         a[i + 1] += a[i] / 10;         //进位 
    20         a[i] %= 10;
    21     }
    22     int x = max(la, lb);        
    23     while(x > 0 && a[x] == 0) x--;    
    24     for(int i = x; i >= 0; --i) printf("%d", a[i]);    
    25     printf("
    ");
    26     return 0;
    27 }

    总结一下,高进度只不过是一个模拟,只要耐心仔细一点,把进位搞明白,就没什么不好写的了。

  • 相关阅读:
    Think in java 4th读书笔记__last update20151130
    Angular学习笔记--last_update 20151106
    程序员技术练级攻略(转载)
    缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题(转载)
    简单理解 RPC(转载)
    Redis 为什么使用单进程单线程方式也这么快(转载)
    redis详解(三)-- 面试题(转载)
    redis应用-sortedset实现排行榜(转载)
    LRU原理和Redis实现——一个今日头条的面试题(转载)
    全面理解Java内存模型(JMM)及volatile关键字(转载)
  • 原文地址:https://www.cnblogs.com/mrclr/p/8520005.html
Copyright © 2011-2022 走看看