鱼C论坛

 找回密码
 立即注册
查看: 847|回复: 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)

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;
    }
}





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

使用道具 举报

发表于 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",程序也能正确处理。同时,输入两个相同的数字不再报错。
想知道小甲鱼最近在做啥?请访问 -> 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-12-22 01:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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