• 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 }
  • 相关阅读:
    MySQL日期函数与日期转换格式化函数大全
    外设驱动库开发笔记19:BMP280压力温度传感器驱动
    外设驱动库开发笔记18:MS5837压力变送器驱动
    通讯接口应用笔记1:RS485通讯上下拉电阻的选择
    外设驱动库开发笔记17:MS5803压力变送器驱动
    外设驱动库开发笔记16:MS5536C压力变送器驱动
    Elasticserach学习笔记之Elasticsearch查询慢和集群慢查询日志配置
    Linux学习笔记之curl模拟get/post/delete/put请求
    ELK学习笔记之elasticsearch中 refresh 和flush区别
    Prometheus学习笔记之Prometheus是如何定义告警级别的
  • 原文地址:https://www.cnblogs.com/areful/p/11849199.html
Copyright © 2020-2023  润新知