Java计算长整数加减(字符串表示)

复习一道老题目,不使用BigInteger,手动计算长整数的加减法(字符串表示,可带符号)。

 

  1 /**
  2  * Created by areful on 2019/11/13
  3  */
  4 public class CalcStringNumber {
  5     private static final String REG_EXP_NUMBER = "0|(-?[1-9]+[0-9]*)";
  6     private static final String REG_EXP_NON_NEGATIVE_NUMBER = "0|([1-9]+[0-9]*)";
  7 
  8     /**
  9      * 带符号相加
 10      */
 11     private static String add(String s1, String s2) {
 12         assert s1.matches(REG_EXP_NUMBER) && s2.matches(REG_EXP_NUMBER);
 13 
 14         boolean isPos1 = s1.charAt(0) != '-';
 15         boolean isPos2 = s2.charAt(0) != '-';
 16 
 17         if (isPos1 && isPos2) {
 18             //都为非负数,直接无符号相加
 19             return addPositive(s1, s2);
 20         } else if (!isPos1 && !isPos2) {
 21             //都为负数,无符号相加再取反
 22             return '-' + addPositive(s1.substring(1), s2.substring(1));
 23         } else if (isPos1) {
 24             //1正,2负,比较字符串长度
 25             if (s1.length() > s2.substring(1).length()) {
 26                 //1比2长,正号
 27                 return subPositive(s1, s2.substring(1));
 28             } else if (s1.length() < s2.substring(1).length()) {
 29                 //1比2短,负号
 30                 return '-' + subPositive(s1, s2.substring(1));
 31             } else {
 32                 //长度相同,去掉符号比较字符串,根据比较结果做绝对值加减,并赋相应符号
 33                 int r = s1.compareTo(s2.substring(1));
 34                 if (r > 0) return subPositive(s1, s2.substring(1));
 35                 else if (r == 0) return "0";
 36                 else return '-' + subPositive(s2.substring(1), s1);
 37             }
 38         } else {
 39             //1负,2正,比较字符串长度
 40             if (s1.substring(1).length() > s2.length()) {
 41                 //1比2长,负号
 42                 return '-' + subPositive(s1.substring(1), s2);
 43             } else if (s1.substring(1).length() < s2.length()) {
 44                 //1比2短,正号
 45                 return subPositive(s2, s1.substring(1));
 46             } else {
 47                 //长度相同,去掉符号比较字符串,根据比较结果做绝对值加减,并赋相应符号
 48                 int r = s1.substring(1).compareTo(s2);
 49                 if (r > 0) return '-' + subPositive(s1.substring(1), s2);
 50                 else if (r == 0) return "0";
 51                 else return subPositive(s2, s1.substring(1));
 52             }
 53         }
 54     }
 55 
 56     /**
 57      * 带符号相减
 58      */
 59     private static String sub(String s1, String s2) {
 60         assert s1.matches(REG_EXP_NUMBER) && s2.matches(REG_EXP_NUMBER);
 61 
 62         boolean isPos1 = s1.charAt(0) != '-';
 63         boolean isPos2 = s2.charAt(0) != '-';
 64 
 65         if (isPos1 && !isPos2) {
 66             //1正,2负,去掉负号,做正整数相加
 67             return addPositive(s1, s2.substring(1));
 68         } else if (!isPos1 && isPos2) {
 69             //1负,2正,绝对值相加再取负号
 70             return '-' + addPositive(s1.substring(1), s2);
 71         } else if (isPos1) {
 72             //均为正,比较字符串长度
 73             if (s1.length() > s2.length()) {
 74                 //1比2长,正号
 75                 return subPositive(s1, s2);
 76             } else if (s1.length() < s2.length()) {
 77                 //1比2短,负号
 78                 return '-' + subPositive(s2, s1);
 79             } else {
 80                 //长度相同,比较字符串,根据比较结果做绝对值加减,并赋相应符号
 81                 int r = s1.compareTo(s2);
 82                 if (r > 0) return subPositive(s1, s2);
 83                 else if (r == 0) return "0";
 84                 else return '-' + subPositive(s2, s1);
 85             }
 86         } else {
 87             //均为负,比较字符串长度
 88             if (s1.length() > s2.length()) {
 89                 //1比2长,负号
 90                 return '-' + subPositive(s1.substring(1), s2.substring(1));
 91             } else if (s1.length() < s2.length()) {
 92                 //1比2短,正号
 93                 return subPositive(s2.substring(1), s1.substring(1));
 94             } else {
 95                 //长度相同,比较字符串,根据比较结果做绝对值加减,并赋相应符号
 96                 int r = s1.compareTo(s2);
 97                 if (r > 0) return '-' + subPositive(s1.substring(1), s2.substring(1));
 98                 else if (r == 0) return "0";
 99                 else return subPositive(s1.substring(1), s2.substring(1));
100             }
101         }
102     }
103 
104     /**
105      * 无符号相加
106      */
107     private static String addPositive(String s1, String s2) {
108         assert s1.matches(REG_EXP_NON_NEGATIVE_NUMBER) && s2.matches(REG_EXP_NON_NEGATIVE_NUMBER);
109 
110         int len1 = s1.length();
111         int len2 = s2.length();
112         int len = Math.max(len1, len2);
113 
114         //暂存计算结果
115         int[] result = new int[len];
116         //进位符号,为1表示有进位
117         int carry = 0;
118         for (int i = 0; i < len; i++) {
119             int a1 = i < len1 ? s1.charAt(len1 - 1 - i) - '0' : 0;
120             int a2 = i < len2 ? s2.charAt(len2 - 1 - i) - '0' : 0;
121             //带进位相加
122             int a = a1 + a2 + carry;
123             result[len - 1 - i] = a % 10;
124             //判断当前计算是否产生进位
125             carry = a > 9 ? 1 : 0;
126         }
127 
128         StringBuilder sb = new StringBuilder();
129         //有进位则头部加1
130         if (carry == 1) sb.append('1');
131         for (int i = 0; i < len; i++) sb.append(result[i]);
132         return trimZero(sb.toString());
133     }
134 
135     /**
136      * 无符号相减
137      */
138     private static String subPositive(String s1, String s2) {
139         assert s1.matches(REG_EXP_NON_NEGATIVE_NUMBER) && s2.matches(REG_EXP_NON_NEGATIVE_NUMBER);
140         if (s1.equals(s2)) return "0";
141 
142         int len1 = s1.length();
143         int len2 = s2.length();
144         int len = Math.max(len1, len2);
145 
146         //暂存计算结果
147         int[] result = new int[len];
148         int carry = 0;
149         for (int i = 0; i < len; i++) {
150             int a1 = i < len1 ? s1.charAt(len1 - 1 - i) - '0' : 0;
151             int a2 = i < len2 ? s2.charAt(len2 - 1 - i) - '0' : 0;
152             //判断低一位计算是否产生借位,如有借位则减1
153             if (carry == 1) a1--;
154             if (a1 >= a2) {
155                 //不需要借位,直接相减
156                 carry = 0;
157                 result[len - 1 - i] = a1 - a2;
158             } else {
159                 //需要借位,置借位标识并相减
160                 carry = 1;
161                 result[len - 1 - i] = a1 + 10 - a2;
162             }
163         }
164 
165         StringBuilder sb = new StringBuilder();
166         for (int i = 0; i < len; i++) sb.append(result[i]);
167         return trimZero(sb.toString());
168     }
169 
170     /**
171      * 移除0开头的数字字符
172      */
173     private static String trimZero(String text) {
174         StringBuilder sb = new StringBuilder();
175         boolean needIgnore = true;
176         for (char c : text.toCharArray()) {
177             if (needIgnore && c == '0') continue;
178             needIgnore = false;
179             sb.append(c);
180         }
181         if (sb.length() == 0) sb.append('0');
182         return sb.toString();
183     }
184 
185     public static void main(String[] args) {
186         assert "0".equals(add("0", "0"));
187         assert "-24".equals(add("-15", "-9"));
188         assert "-6".equals(add("-15", "9"));
189         assert "6".equals(add("15", "-9"));
190         assert "24".equals(add("15", "9"));
191         assert "2468".equals(add("1234", "1234"));
192         assert "10470".equals(add("5235", "5235"));
193         assert "0".equals(add("-1234", "1234"));
194         assert "0".equals(add("1234", "-1234"));
195         assert "-1".equals(add("1234", "-1235"));
196         assert "1".equals(add("-1234", "1235"));
197         assert "6".equals(add("15", "-9"));
198         assert "-6".equals(add("-15", "9"));
199         assert "24700000000000000000000000000000000000000000000000".equals(
200                 add("12350000000000000000000000000000000000000000000000", "12350000000000000000000000000000000000000000000000"));
201 
202         assert "0".equals(sub("0", "0"));
203         assert "6".equals(sub("-9", "-15"));
204         assert "-24".equals(sub("-9", "15"));
205         assert "24".equals(sub("9", "-15"));
206         assert "-6".equals(sub("9", "15"));
207         assert "6".equals(sub("15", "9"));
208         assert "-6".equals(sub("-15", "-9"));
209         assert "-24".equals(sub("-15", "9"));
210         assert "24".equals(sub("15", "-9"));
211         assert "6".equals(sub("15", "9"));
212         assert "-2469".equals(sub("-1234", "1235"));
213         assert "-1".equals(sub("1234", "1235"));
214         assert "0".equals(sub("1234", "1234"));
215         assert "0".equals(sub("-1234", "-1234"));
216         assert "-1234".equals(sub("0", "1234"));
217         assert "1234".equals(sub("0", "-1234"));
218         assert "1234".equals(sub("1234", "0"));
219         assert "24700000000000000000000000000000000000000000000000".equals(
220                 sub("12350000000000000000000000000000000000000000000000", "-12350000000000000000000000000000000000000000000000"));
221     }
222 }

 

posted on 2019-11-13 14:54  areful  阅读(1047)  评论(0编辑  收藏  举报

导航