naeb 发表于 2023-3-19 19:07:59

使用链表实现高精度整数加减法运算(JAVA)

本帖最后由 naeb 于 2023-3-19 19:07 编辑

使用链表实现高精度整数加减法运算
输入数据可以采用每三位整数一组(中间加逗号),也可以不加逗号(比如: 100000000)。
(1)0;0;+ ,输出“0”。
(2)100,100,100;100,100,100,+,输出:200,200,200
(4)自选数据



问两个问题,我输入两个相同的数字后就会报错。另外我想要输入的数据中间加逗号要怎么改动?


请输入a:0
请输入b:0
请输入运算符:+
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: begin -3, end 0, length 0
        at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3319)
        at java.base/java.lang.String.substring(String.java:1874)
        at test.CopyOfIntegerAddSub.displayWithComma(CopyOfIntegerAddSub.java:229)
        at test.CopyOfIntegerAddSub.main(CopyOfIntegerAddSub.java:33)


package test;


import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Scanner;

public class CopyOfIntegerAddSub {

    public static void main(String[] args) {
      Scanner scan = new Scanner(System.in);
      System.out.print("请输入a:");
      String str_a = scan.next();
      LinkedList list_a = Str2List(str_a);
      System.out.print("请输入b:");
      String str_b = scan.next();
      LinkedList list_b = Str2List(str_b);
      System.out.print("请输入运算符:");
      String str_s = scan.next();
      String str_pd = check(str_a, str_b, str_s); // 检查
      Map map = Compare(list_a, list_b);

      LinkedList max = (LinkedList) map.get("max");
      LinkedList min = (LinkedList) map.get("min");
      LinkedList flag = (LinkedList) map.get("flag");
      //System.out.println(flag);

      if (str_pd.length() > 0) {
            System.out.println(str_pd);
      } else {
            if (str_s.equals("+")||max != min) {
                String result_add = displayWithComma(add(max,min));
                System.out.println("加法结果为:" + result_add);
            } else if (str_s.equals("-")||max!=min) {
                String result_sub = displayWithComma(sub(max, min));
                if(flag.getFirst().equals("-")){
                  result_sub = "-" + result_sub;
                }
                System.out.println("减法结果为:" + result_sub);
            }
      }

    }


    /**
   * 加法
   *
   * @param a
   * @param b
   * @return
   */
    private static String add(LinkedList max, LinkedList min) {
      int carry = 0; // 是否进位,1为进位
      int r = 0; // 每位相加的结果
      LinkedList result = new LinkedList();

      int size_max = max.size(); // 链表a的长度
      int size_min = min.size(); // 链表b的长度

      for (int i = 0; i < size_max; i++) {
            int max_i = Integer.parseInt(max.get(i).toString());
            int min_i;
            if (i < size_min) {
                min_i = Integer.parseInt(min.get(i).toString());
            } else {
                min_i = 0;
            }
            r = max_i + min_i + carry;
            if (r < 10) {
                result.addFirst(r);
                carry = 0;
            } else {
                result.addFirst(r % 10);
                carry = 1;
                if (i == size_max - 1) { // 控制最后一次循环;如果不加,最后一位相加时,不会把1存入链表
                  result.addFirst(carry);
                }
            }
      }

      String str = "";
      for (int i = 0; i < result.size(); i++) {
            str = str + result.get(i).toString();
      }
      return str;
    }


    /**
   * 减法
   *
   * @param a
   * @param b
   * @return
   */
    private static String sub(LinkedList max, LinkedList min) {
      int borrow = 0; // 是否借位 1借
      int r = 0; // 每位相减的结果
      LinkedList result = new LinkedList();

      int size_max = max.size(); // 链表a的长度
      int size_min = min.size(); // 链表b的长度

      for (int i = 0; i < size_max; i++) {
            int max_i = Integer.parseInt(max.get(i).toString());
            int min_i;
            if (i < size_min) {
                min_i = Integer.parseInt(min.get(i).toString());
            } else {
                min_i = 0;
            }
            r = max_i - min_i - borrow;
            if (r < 0) {
                result.addFirst(r + 10);
                borrow = 1;
            } else {
                if (i == size_max - 1 && r == 0) { // 控制最后一次循环,两数相减如果为0,不显示0
                  break;
                }
                result.addFirst(r);
                borrow = 0;
            }
      }

      String str = "";
      for (int i = 0; i < result.size(); i++) {
            str = str + result.get(i).toString();
      }
      return str;
    }


    /**
   * 比较大小
   * @param a
   * @param b
   * @return
   */
    private static Map<String, LinkedList> Compare(LinkedList a, LinkedList b) {

      Map<String, LinkedList> map = new HashMap<String, LinkedList>(); // 为了可以返回多个值

      int size_a = a.size(); // 链表a的长度
      int size_b = b.size(); // 链表b的长度

      LinkedList max = new LinkedList();
      LinkedList min = new LinkedList();

      LinkedList flag = new LinkedList();

      if (size_a > size_b) {
            max = a;
            min = b;
            flag.addFirst("+");
      } else if (size_a < size_b) {
            max = b;
            min = a;
            flag.addFirst("-");
      } else {
            for (int i = 0; i < size_a; i++) {
                int a_i = Integer.parseInt(a.get(size_a - 1 - i).toString());
                int b_i = Integer.parseInt(b.get(size_b - 1 - i).toString());
                if (a_i == b_i) {
                  continue;
                } else if (a_i < b_i) {
                  flag.addFirst("-");
                  max = b;
                  min = a;
                  break;
                } else {
                  flag.addFirst("+");
                  max = a;
                  min = b;
                  break;
                }
            }

      }
      map.put("max", max);
      map.put("min", min);
      map.put("flag", flag);
      return map;
    }


    /**
   * 把字符串传入链表
   *
   * @param str
   * @return
   */
    private static LinkedList Str2List(String str) {
      LinkedList<Character> list = new LinkedList<Character>();
      for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            list.addFirst(c);

      }
      // System.out.println("输出:"+list);
      return list;
    }


    /**
   * 处理字符串,每3位一格
   *
   * @param str
   * @return
   */
    public static String displayWithComma(String str) {
      str = new StringBuffer(str).reverse().toString(); // 先将字符串颠倒顺序
      String str2 = "";

      int size = (str.length() % 3 == 0) ? (str.length() / 3)
                : (str.length() / 3 + 1); // 每三位取一长度

      /*
         * 比如把一段字符串分成n段,第n段可能不是三个数,有可能是一个或者两个,
         * 现将字符串分成两部分.一部分为前n-1段,第二部分为第n段.前n-1段,每一段加一",".而第n段直接取出即可
         */

            for (int i = 0; i < size - 1; i++) { // 前n-1段
                str2 += str.substring(i * 3, i * 3 + 3) + ",";
            }

            for (int i = size - 1; i < size; i++) { // 第n段
                str2 += str.substring(i * 3, str.length());
            }

            str2 = new StringBuffer(str2).reverse().toString();

            return str2;
      }


    /**
   * 判断是否为数字
   * @param str
   * @return
   */
    public static boolean isNumeric(String str) {
      for (int i = str.length(); --i >= 0;) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
      }
      return true;
    }


    /**
   * 检查合法性
   * @param str_a
   * @param str_b
   * @param str_s
   * @return
   */
    private static String check(String str_a, String str_b, String str_s) {
      boolean result = true;
      String str = "";
      if ( isNumeric(str_a) == false) {
            str = str + " a 为非法数值";
      }
      if (isNumeric(str_b) == false) {
            str = str + " b 为非法数值";
      }
      if (!((str_s.equals("+")) || (str_s.equals("-")))) {
            str = str + " 非法运算符";
      }
      return str;
    }
}





isdkz 发表于 2023-3-19 19:11:47

问题1:输入两个相同的数字后就会报错。
问题2:想要输入的数据中间加逗号要怎么改动?

首先,问题1是因为在 displayWithComma 函数中,当输入的字符串长度为 0 时,会导致计算 size 的逻辑出现问题。可以对此情况进行特殊处理,避免这个问题。问题2的话,我们可以在 Str2List 函数中先处理输入的字符串,去除其中的逗号。

解决方法如下:

修改 displayWithComma 函数,在开头添加对长度为 0 的特殊处理:

public static String displayWithComma(String str) {
    if (str.length() == 0) {
      return "0";
    }
    // 其余代码保持不变
}

修改 Str2List 函数,在开始时添加一段代码以删除输入字符串中的逗号:

private static LinkedList Str2List(String str) {
    str = str.replace(",", ""); // 增加这一行,删除字符串中的逗号
    LinkedList<Character> list = new LinkedList<Character>();
    // 其余代码保持不变
}

这样,问题1和问题2都应该得到解决。现在您可以输入带有逗号的数字,例如 "100,000,000",程序也能正确处理。同时,输入两个相同的数字不再报错。

naeb 发表于 2023-3-19 21:01:01

isdkz 发表于 2023-3-19 19:11
问题1:输入两个相同的数字后就会报错。
问题2:想要输入的数据中间加逗号要怎么改动?



改完后输入其他的数据输出结果都显示0,加入逗号后还是和以前一样会显示非法数值
页: [1]
查看完整版本: 使用链表实现高精度整数加减法运算(JAVA)