zoukankan      html  css  js  c++  java
  • C++实现两个大整数的相加(考虑到负数异常情况)

    实现两个大整数的相加,首先应该排除直接使用int和long long的方法,这些方法很容易溢出,这里为了方便(是否可以使用更精简的结构存储?)采用char来存储整数,整体思路如下:

    1. 对于整数n和m的字符串形式,按照数组索引的从大到小累加计算,直接将结果存储到对应的result字符串中,处理完毕后再将result逆序输出,需考虑0和-的输出情况;

    2. 考虑到有负号的情况,一开始就需要判断负号字符,这里将(-,-)和(+,+)统一当成相加操作然后都是负号的话在结尾补上负号,对于(+,-)和(-,+)统一处理成(大-小)的形式然后在结尾补负号;比如对于20-500转换成-(-20+500),对于-500+20准换成-(500-20)。

    3. 这里需要使用标志位nTake记录是否进位或借位;

    4. 还要考虑是否有异常字符出现,使用全局变量gInvalid记录有无异常。

      1 #include<stdio.h>
      2 #include<string.h>
      3 
      4 #define Joshua_OJ
      5 
      6 bool gInvalid = false;
      7 
      8 // 0: equal, -1: n less m, 1: n bigger m
      9 int AbsIsEqual(char* n, char* m, int n_start, int n_end, int m_start, int m_end)
     10 {
     11     if ((n_end - n_start) > (m_end - m_start)) return 1;
     12     else if ((n_end - n_start) < (m_end - m_start)) return -1;
     13     else
     14     {
     15         int i = n_start;
     16         int j = m_start;
     17         while (i <= n_end && j <= m_end)
     18         {
     19             if (n[i] > m[j]) return 1;
     20             else if (n[i] < m[j]) return -1;
     21             ++i;
     22             ++j;
     23         }
     24     }
     25     return 0;
     26 }
     27 
     28 void BigNumberAdd(char* n, char* m, char* result)
     29 {
     30     gInvalid = false;
     31 
     32     if (n == NULL || m == NULL)
     33     {
     34         gInvalid = true;
     35         return;
     36     }
     37 
     38     int n_index = strlen(n) - 1;
     39     int m_index = strlen(m) - 1;
     40 
     41     // 负数特别处理
     42     int n_start = 0;
     43     int m_start = 0;
     44     int n_signed = 1;
     45     int m_signed = 1;
     46     if (n[0] == '-')
     47     {
     48         n_start = 1;
     49         n_signed = -1;
     50     }
     51     if (m[0] == '-')
     52     {
     53         m_start = 1;
     54         m_signed = -1;
     55     }
     56     // 如果只有一个负数,转换为大数减小数再取负号,这样方便异号借位相减
     57     bool isResetPosNeg = false;
     58     if (n_signed == 1 && m_signed == -1)
     59     {
     60         int tag = AbsIsEqual(n, m, n_start, n_index, m_start, m_index);
     61         if (tag == -1)
     62         {
     63             n_signed = 0 - n_signed;
     64             m_signed = 0 - m_signed;
     65             isResetPosNeg = true;
     66         }
     67         else if (tag == 0)
     68         {
     69             result[0] = '0';
     70             result[1] = '';
     71             return;
     72         }
     73     }
     74     else if (n_signed == -1 && m_signed == 1)
     75     {
     76         int tag = AbsIsEqual(n, m, n_start, n_index, m_start, m_index);
     77         if (tag == 1)
     78         {
     79             n_signed = 0 - n_signed;
     80             m_signed = 0 - m_signed;
     81             isResetPosNeg = true;
     82         }
     83         else if (tag == 0)
     84         {
     85             result[0] = '0';
     86             result[1] = '';
     87             return;
     88         }
     89     }
     90 
     91     int index = 0;
     92     int nTake = 0;
     93     while (n_index >= n_start || m_index >= m_start)
     94     {
     95         int op1, op2;
     96         op1 = op2 = 0;
     97 
     98         if (n_index >= n_start && (n[n_index] < '0' || n[n_index] > '9'))
     99         {
    100             gInvalid = true;
    101             return;
    102         }
    103         if (m_index >= m_start && (m[m_index] < '0' || m[m_index] > '9'))
    104         {
    105             gInvalid = true;
    106             return;
    107         }
    108 
    109         if (n_index >= n_start) op1 = n[n_index] - '0';
    110         if (m_index >= m_start) op2 = m[m_index] - '0';
    111         if (n_signed == 1 && m_signed == -1) op2 = m_signed * op2;
    112         else if (m_signed == 1 && n_signed == -1) op1 = n_signed * op1;
    113 
    114         int nSum = op1 + op2 + nTake;
    115         if (nSum >= 10)
    116         {
    117             nSum -= 10;
    118             result[index] = nSum + '0';
    119             nTake = 1;
    120         }
    121         else if (nSum >= 0)
    122         {
    123             result[index] = nSum + '0';
    124             nTake = 0;
    125         }
    126         else
    127         {
    128             nSum = 10 + nSum;
    129             result[index] = nSum + '0';
    130             nTake = -1;
    131         }
    132         --n_index;
    133         --m_index;
    134         ++index;
    135     }
    136 
    137     if (nTake == 1) result[index++] = nTake + '0';
    138     else if (nTake == -1) result[index++] = '-';
    139 
    140     if (isResetPosNeg) result[index++] = '-';
    141     else if (n_signed == -1 && m_signed == -1) result[index++] = '-';
    142 
    143     result[index] = '';
    144 }
    145 
    146 // 从后往前打印出这个数字,并忽略开头的0
    147 void PrintNumber(char* number)
    148 {
    149     bool isBeginning0 = true;
    150     int length = strlen(number);
    151 
    152     for (int i = length - 1; i >= 0; --i)
    153     {
    154         if (i == length - 1 && number[i] == '-')
    155         {
    156             printf("%c", '-');
    157             continue;
    158         }
    159 
    160         if (isBeginning0 && number[i] != '0')
    161         {
    162             isBeginning0 = false;
    163         }
    164 
    165         if (!isBeginning0)
    166         {
    167             printf("%c", number[i]);
    168         }
    169         else
    170         {
    171             if (i == 0) printf("%c", '0');
    172         }
    173     }
    174 }
    175 
    176 int main(void)
    177 {
    178     #ifdef Joshua_OJ
    179     freopen("in.txt", "r", stdin);
    180     #endif
    181     int num;
    182     char n[10000];
    183     char m[10000];
    184     char result[10002];
    185 
    186     scanf("%d", &num);
    187     while (num--)
    188     {
    189         scanf("%s %s", n, m);
    190         BigNumberAdd(n, m, result);
    191         if (gInvalid)
    192         {
    193             printf("%s
    ", "invalid number");
    194             continue;
    195         }
    196         PrintNumber(result);
    197         printf("
    ");
    198     }
    199 
    200     #ifdef Joshua_OJ
    201     fclose(stdin);
    202     #endif
    203 
    204     return 0;
    205 }

    输入第一个数表示有多少组数据,对于无效数据需要输出invalid number

    Input:

    15
    200 -22
    22 -200
    -200 22
    -22 200
    0 0
    000 000
    -111 -111
    -50 50
    50 -50
    -333 -333
    222 -100
    222.222 222
    123222222222456 89701234562222222
    11111111111111111 11111111111111100
    9999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999

    Output:

    178
    -178
    -178
    178
    0
    0
    -222
    0
    0
    -666
    122
    invalid number
    89824456784444678
    22222222222222211
    19999999999999999999999999999999999999999999999999999998

  • 相关阅读:
    LeetCode 227. Basic Calculator II
    LeetCode 224. Basic Calculator
    LeetCode 103. Binary Tree Zigzag Level Order Traversal
    LeetCode 102. Binary Tree Level Order Traversal
    LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode 169. Majority Element
    LeetCode 145. Binary Tree Postorder Traversal
    LeetCode 94. Binary Tree Inorder Traversal
    LeetCode 144. Binary Tree Preorder Traversal
  • 原文地址:https://www.cnblogs.com/JoshuaMK/p/big_int_add.html
Copyright © 2011-2022 走看看