鱼C论坛

 找回密码
 立即注册
查看: 604|回复: 2

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

[复制链接]
发表于 2023-3-19 19:07:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 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)


  1. package test;


  2. import java.util.HashMap;
  3. import java.util.LinkedList;
  4. import java.util.Map;
  5. import java.util.Scanner;

  6. public class CopyOfIntegerAddSub {

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

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

  23.         if (str_pd.length() > 0) {
  24.             System.out.println(str_pd);
  25.         } else {
  26.             if (str_s.equals("+")||max != min) {
  27.                 String result_add = displayWithComma(add(max,min));
  28.                 System.out.println("加法结果为:" + result_add);
  29.             } else if (str_s.equals("-")||max!=min) {
  30.                 String result_sub = displayWithComma(sub(max, min));
  31.                 if(flag.getFirst().equals("-")){
  32.                     result_sub = "-" + result_sub;
  33.                 }
  34.                 System.out.println("减法结果为:" + result_sub);
  35.             }
  36.         }

  37.     }


  38.     /**
  39.      * 加法
  40.      *
  41.      * @param a
  42.      * @param b
  43.      * @return
  44.      */
  45.     private static String add(LinkedList max, LinkedList min) {
  46.         int carry = 0; // 是否进位,1为进位
  47.         int r = 0; // 每位相加的结果
  48.         LinkedList result = new LinkedList();

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

  51.         for (int i = 0; i < size_max; i++) {
  52.             int max_i = Integer.parseInt(max.get(i).toString());
  53.             int min_i;
  54.             if (i < size_min) {
  55.                 min_i = Integer.parseInt(min.get(i).toString());
  56.             } else {
  57.                 min_i = 0;
  58.             }
  59.             r = max_i + min_i + carry;
  60.             if (r < 10) {
  61.                 result.addFirst(r);
  62.                 carry = 0;
  63.             } else {
  64.                 result.addFirst(r % 10);
  65.                 carry = 1;
  66.                 if (i == size_max - 1) { // 控制最后一次循环;如果不加,最后一位相加时,不会把1存入链表
  67.                     result.addFirst(carry);
  68.                 }
  69.             }
  70.         }

  71.         String str = "";
  72.         for (int i = 0; i < result.size(); i++) {
  73.             str = str + result.get(i).toString();
  74.         }
  75.         return str;
  76.     }


  77.     /**
  78.      * 减法
  79.      *
  80.      * @param a
  81.      * @param b
  82.      * @return
  83.      */
  84.     private static String sub(LinkedList max, LinkedList min) {
  85.         int borrow = 0; // 是否借位 1借
  86.         int r = 0; // 每位相减的结果
  87.         LinkedList result = new LinkedList();

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

  90.         for (int i = 0; i < size_max; i++) {
  91.             int max_i = Integer.parseInt(max.get(i).toString());
  92.             int min_i;
  93.             if (i < size_min) {
  94.                 min_i = Integer.parseInt(min.get(i).toString());
  95.             } else {
  96.                 min_i = 0;
  97.             }
  98.             r = max_i - min_i - borrow;
  99.             if (r < 0) {
  100.                 result.addFirst(r + 10);
  101.                 borrow = 1;
  102.             } else {
  103.                 if (i == size_max - 1 && r == 0) { // 控制最后一次循环,两数相减如果为0,不显示0
  104.                     break;
  105.                 }
  106.                 result.addFirst(r);
  107.                 borrow = 0;
  108.             }
  109.         }

  110.         String str = "";
  111.         for (int i = 0; i < result.size(); i++) {
  112.             str = str + result.get(i).toString();
  113.         }
  114.         return str;
  115.     }


  116.     /**
  117.      * 比较大小
  118.      * @param a
  119.      * @param b
  120.      * @return
  121.      */
  122.     private static Map<String, LinkedList> Compare(LinkedList a, LinkedList b) {

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

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

  126.         LinkedList max = new LinkedList();
  127.         LinkedList min = new LinkedList();

  128.         LinkedList flag = new LinkedList();

  129.         if (size_a > size_b) {
  130.             max = a;
  131.             min = b;
  132.             flag.addFirst("+");
  133.         } else if (size_a < size_b) {
  134.             max = b;
  135.             min = a;
  136.             flag.addFirst("-");
  137.         } else {
  138.             for (int i = 0; i < size_a; i++) {
  139.                 int a_i = Integer.parseInt(a.get(size_a - 1 - i).toString());
  140.                 int b_i = Integer.parseInt(b.get(size_b - 1 - i).toString());
  141.                 if (a_i == b_i) {
  142.                     continue;
  143.                 } else if (a_i < b_i) {
  144.                     flag.addFirst("-");
  145.                     max = b;
  146.                     min = a;
  147.                     break;
  148.                 } else {
  149.                     flag.addFirst("+");
  150.                     max = a;
  151.                     min = b;
  152.                     break;
  153.                 }
  154.             }

  155.         }
  156.         map.put("max", max);
  157.         map.put("min", min);
  158.         map.put("flag", flag);
  159.         return map;
  160.     }


  161.     /**
  162.      * 把字符串传入链表
  163.      *
  164.      * @param str
  165.      * @return
  166.      */
  167.     private static LinkedList Str2List(String str) {
  168.         LinkedList<Character> list = new LinkedList<Character>();
  169.         for (int i = 0; i < str.length(); i++) {
  170.             char c = str.charAt(i);
  171.             list.addFirst(c);

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


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

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

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

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

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

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

  198.             return str2;
  199.         }


  200.     /**
  201.      * 判断是否为数字
  202.      * @param str
  203.      * @return
  204.      */
  205.     public static boolean isNumeric(String str) {
  206.         for (int i = str.length(); --i >= 0;) {
  207.             if (!Character.isDigit(str.charAt(i))) {
  208.                 return false;
  209.             }
  210.         }
  211.         return true;
  212.     }


  213.     /**
  214.      * 检查合法性
  215.      * @param str_a
  216.      * @param str_b
  217.      * @param str_s
  218.      * @return
  219.      */
  220.     private static String check(String str_a, String str_b, String str_s) {
  221.         boolean result = true;
  222.         String str = "";
  223.         if ( isNumeric(str_a) == false) {
  224.             str = str + " a 为非法数值";
  225.         }
  226.         if (isNumeric(str_b) == false) {
  227.             str = str + " b 为非法数值";
  228.         }
  229.         if (!((str_s.equals("+")) || (str_s.equals("-")))) {
  230.             str = str + " 非法运算符";
  231.         }
  232.         return str;
  233.     }
  234. }
复制代码






想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

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

解决方法如下:

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

  1. public static String displayWithComma(String str) {
  2.     if (str.length() == 0) {
  3.         return "0";
  4.     }
  5.     // 其余代码保持不变
  6. }
复制代码


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

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


这样,问题1和问题2都应该得到解决。现在您可以输入带有逗号的数字,例如 "100,000,000",程序也能正确处理。同时,输入两个相同的数字不再报错。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

改完后输入其他的数据输出结果都显示0,加入逗号后还是和以前一样会显示非法数值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-26 10:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表