ArrayIndexOutOfBoundsException异常十的补算法实现 [英] ArrayIndexOutOfBoundsException in ten's complement arithmetic implementation

查看:183
本文介绍了ArrayIndexOutOfBoundsException异常十的补算法实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的code试图实现一个算法


  • 需要用户输入两个整数和一个操作数 + - 从控制台,

  • 存储这些数字位数由位在 INT [50] 中的十位补格式,

  • 执行(十进制)数字逐位加/减运算,

  • 打印出结果以十进制格式,没有前导零。

不过,在我目前的实现有两个问题


  • 当加入99 + 9999,打印的结果是01098,而不是预期的010098。

  • 当减去99 - 9999,我得到一个 ArrayIndexOutOfBoundsException异常:50 而不是预期的结果-09900

进口的java.util。*;公共类Program9 {
    公共静态字符串getOperand(){
        扫描程序扫描=新的扫描仪(System.in);
        串stringOfInteger;        System.out.print(请输入一个整数多达50个数字:);
        stringOfInteger = scan.nextLine();
        返回stringOfInteger;
    }    公共静态INT []转换(字符串操作数){
        INT []整数= INT新[50];
        焦炭CH;        INT位置= operand.length() - 1;
        的for(int i = integer.length - 1; I> = 0;我 - ){
            如果(位置> = 0)
                CH = operand.charAt(position--);
            其他
                CH = 0;
            如果(CH&GT ='0'和;&放大器;沟道&下; ='9'){
                整数[i] = CH - '0';
            }其他{
                整数[I] = 0;
            }
        }
        返回整数;
    }    公共静态INT []加(INT []操作数,INT []操作数){
        INT []结果=新的INT [operand1.length]
        INT携带= 0;
        的for(int i = operand1.length - 1; I> = 0;我 - ){
            结果[I] =操作数[I] +操作数[I] +随身携带;
            如果(导致由[i] / 10 == 1){
                结果[I] =结果[I]%10;
                携带= 1;
            }其他
                携带= 0;
        }
        返回结果;
    }    公共静态INT []补(INT []操作数){
        INT []结果=新的INT [operand.length]
        的for(int i = operand.length - 1; I> = 0;我 - )
            结果[I] = 9 - 操作数[I]
        返回结果;
    }    公共静态INT [] ADD1(INT []操作数){
        INT []结果=新INT [50];
        结果[49] = 1;
        的for(int i = result.length - 2; I> = 0;我 - )
            结果由[i] = 0;
        返回结果;
    }    公共静态INT []否定(INT []操作数){
        返回加(ADD1(操作数),补体(操作数));
    }    公共静态无效打印(INT []因此,字符串操作){
        如果(operation.charAt(0)=='+')
            System.out.print(两整数的大部=);
        否则如果(operation.charAt(0)==' - ')
            System.out.print(两个整数的减法=);
        如果(导致[0] == 9){
            结果=否定(结果);
            System.out.print( - );
            的for(int i = 0; I< result.length;我++){
                如果(结果[I] == 0安培;&安培;结果[I + 1] == 0)
                    继续;
                其他
                    System.out.print(结果[I]);
            }
        }其他
            的for(int i = 0; I< result.length;我++){
                如果(结果[I] == 0安培;&安培;结果[I + 1] == 0)
                    继续;
                其他
                    System.out.print(结果[I]);
            }
        的System.out.println();
    }    公共静态无效的主要(字串[] args){
        扫描程序扫描=新的扫描仪(System.in);
        INT []结果=新INT [50];
        字符串字符串1 = getOperand();
        字符串字符串2 = getOperand();
        INT [] =数字integer1转换(字符串1);
        INT [] =整数2转换(字符串2);
        字符串操作;        System.out.print(请输入动作进行使用(+或 - ):);
        操作= scan.nextLine();
        如果(operation.charAt(0)=='+')
            ADD(数字integer1,整数2);
        否则如果(operation.charAt(0)==' - ')
            整数2 =否定(整数2);        结果=添加(数字integer1,整数2);        的System.out.println(Arrays.toString(数字integer1));
        的System.out.println(Arrays.toString(整数2));
        的System.out.println(Arrays.toString(添加(数字integer1,整数2)));
        打印(因此,在操作)​​;
    }
}


解决方案

好了,经过了这么多的讨论和这么多的问题与你的code我已经完全修改原来的code,因为你说你想学习更多。在其它的改进我也做了以下变化:


  • Meaninfgul类名

  • 有意义的方法和参数名称

  • 转换重复和经常使用的常数像 50 和阵列重新数量presentation 1 (需要否定)转换成清洁code原因静态final成员(文档,在一个地方容易变化的,有意义的名称),运行时优化)。

  • 延长code允许负整数作为操作数

  • 添加验证模式的用户输入。例如。现在的最大数量的长度,以避免阵列溢检查。

  • 避免计算过程中数值溢出通过使阵列比允许用户输入的最大位数越大(见源$ C ​​$ C评论)

  • 添加重试循环处理与操作数和操作员输入,提取控制台处理成一个parametrised方法错误。

  • 简化$ C $通过,因为用户输入其转换成 INT [] 之前已经验证去除不必要的检查温度。

  • 请调试输出可选

包de.scrum_master.stackoverflow;进口java.util.Arrays中;
进口java.util.Scanner中;
进口的java.util.regex.Pattern;公共类TensComplementArithmetic {
    //打印调试消息?
    私有静态最终布尔DEBUG = TRUE;    //用于由用户输入的数字的最大长度
    //(位数不包括可选+/-号)
    私有静态最终诠释MAX_NUMBER_LENGTH = 50;    //数组必须有标志一个额外的元素,
    //多一个,以避免溢出将大负数时
    私有静态最终诠释ARRAY_LENGTH = MAX_NUMBER_LENGTH + 2;    //扫描仪作为控制台输入处理
    私有静态最后的扫描仪INPUT_SCANNER =新的扫描仪(System.in);    //为正/负整数格式验证包括正则表达式。长度检查
    私有静态最终模式INTEGER_PATTERN = Pattern.compile([+ - ] [0-9] {1,?+ MAX_NUMBER_LENGTH +});    //正则表达式模式操作员验证(目前仅+​​/ - 允许的)
    私有静态最终模式OPERATOR_PATTERN = Pattern.compile([+ - ]);    //数1总是需要用于将9的成10的补
    //否定过程中,所以我们把它定义为一个可重用的常量
    私有静态最终诠释[] NUMBER_ONE;    静态的 {
        //初始化恒载阵列重新presentation为1号
        NUMBER_ONE =新INT [ARRAY_LENGTH]
        NUMBER_ONE [ARRAY_LENGTH - 1] = 1;
    }    公共静态字符串readConsoleInput(字符串提示模式validationPattern,弦乐的errorMessage){
        字符串输入= NULL;
        而(输入== NULL){
            System.out.print(提示+:);
            如果(INPUT_SCANNER.hasNext(validationPattern))
                输入= INPUT_SCANNER.next(validationPattern);
            其他{
                INPUT_SCANNER.nextLine();
                的System.out.println(的errorMessage);
            }
        }
        返回输入;
    }    公共静态字符串getOperand(字符串operandName){
        返回readConsoleInput(
            操作数+ operandName,
            INTEGER_PATTERN,
            非法数字格式,请输入最大的正/负的整数。+ MAX_NUMBER_LENGTH +数字。
        );
    }    私人静态字符串getOperator(){
        返回readConsoleInput(
            算术运算符(+或 - ),
            OPERATOR_PATTERN,
            未知运营商,再试一次。
        );
    }    公共静态INT [] parseInteger(串号){
        字符符号= number.charAt(0);
        布尔isNegative等号(=)=​​=' - '?真假;
        如果(isNegative ||登录=='+')
            数= number.substring(1);        INT []结果=新的INT [ARRAY_LENGTH]
        INT的ParsePosition = number.length() - 1;
        的for(int i = result.length - 1; I> = 0;我 - ){
            如果(一个ParsePosition℃,)
                打破;
            结果[I] = number.charAt(parsePosition--) - '0';
        }
        返回isNegative?否定(结果):结果;
    }    公共静态INT []加(INT []操作数,INT []操作数){
        INT []结果=新的INT [ARRAY_LENGTH]
        INT携带= 0;        的for(int i = ARRAY_LENGTH - 1; I> = 0;我 - ){
            结果[I] =操作数[I] +操作数[I] +随身携带;
            如果(结果[Ⅰ]≥= 10){
                结果[I] =结果[I]%10;
                携带= 1;
            }其他
                携带= 0;
        }
        返回结果;
    }    公共静态INT []补(INT []操作数){
        INT []结果=新的INT [ARRAY_LENGTH]        的for(int i = operand.length - 1; I> = 0;我 - )
            结果[I] = 9 - 操作数[I]
        返回结果;
    }    公共静态INT []否定(INT []操作数){
        返回加(补码(操作数),NUMBER_ONE);
    }    公共静态无效打印(INT []因此,字符串操作){
        System.out.print(?operation.charAt(0)==' - '差=:和=);
        如果(导致[0] == 9){
            结果=否定(结果);
            System.out.print( - );
        }
        布尔leadingZero =真;
        的for(int i = 0; I< result.length;我++){
            如果(leadingZero){
                如果(结果[I] == 0)
                    继续;
                leadingZero = FALSE;
            }
            System.out.print(结果[I]);
        }
        的System.out.println(leadingZero0:);
    }    公共静态无效的主要(字串[] args){
        INT [] =操作数parseInteger(getOperand(#1));
        INT []操作数2 = parseInteger(getOperand(#2));
        字符串运算符= getOperator();        如果(operator.equals( - ))
            操作数=取反(操作数);        INT []结果=新的INT [ARRAY_LENGTH]
        结果=添加(操作数,操作数);
        如果(调试){
            的System.out.println(操作数1 =+ Arrays.toString(操作数));
            的System.out.println(操作数2 =+ Arrays.toString(操作数));
            的System.out.println(结果=+ Arrays.toString(结果));
        }
        打印(结果,操作者);
    }
}

My code tries to implement an algorithm to

  • take user input for two integer numbers and an operand + or - from the console,
  • store those numbers digit by digit in an int[50], representing negative ones in ten's complement format,
  • implement (decimal) digit-by-digit add/subtract operations,
  • print the result in decimal format without leading zeroes.

However, in my current implementation there are two problems

  • When adding 99 + 9999, the printed result is 01098 instead of the expected 010098.
  • When subtracting 99 - 9999, I get an ArrayIndexOutOfBoundsException: 50 instead of the expected result -09900.

import java.util.*;

public class Program9 {
    public static String getOperand() {
        Scanner scan = new Scanner(System.in);
        String stringOfInteger;

        System.out.print("Please enter an integer up to 50 numbers: ");
        stringOfInteger = scan.nextLine();
        return stringOfInteger;
    }

    public static int[] convert(String operand) {
        int[] integer = new int[50];
        char ch;

        int position = operand.length() - 1;
        for (int i = integer.length - 1; i >= 0; i--) {
            if (position >= 0)
                ch = operand.charAt(position--);
            else
                ch = 0;
            if (ch >= '0' && ch <= '9') {
                integer[i] = ch - '0';
            } else {
                integer[i] = 0;
            }
        }
        return integer;
    }

    public static int[] add(int[] operand1, int[] operand2) {
        int[] result = new int[operand1.length];
        int carry = 0;
        for (int i = operand1.length - 1; i >= 0; i--) {
            result[i] = operand1[i] + operand2[i] + carry;
            if (result[i] / 10 == 1) {
                result[i] = result[i] % 10;
                carry = 1;
            } else
                carry = 0;
        }
        return result;
    }

    public static int[] complement(int[] operand) {
        int[] result = new int[operand.length];
        for (int i = operand.length - 1; i >= 0; i--)
            result[i] = 9 - operand[i];
        return result;
    }

    public static int[] add1(int[] operand) {
        int[] result = new int[50];
        result[49] = 1;
        for (int i = result.length - 2; i >= 0; i--)
            result[i] = 0;
        return result;
    }

    public static int[] negate(int[] operand) {
        return add(add1(operand), complement(operand));
    }

    public static void print(int[] result, String operation) {
        if (operation.charAt(0) == '+')
            System.out.print("The subtotal of the two integer = ");
        else if (operation.charAt(0) == '-')
            System.out.print("The substraction of the two integers = ");
        if (result[0] == 9) {
            result = negate(result);
            System.out.print("-");
            for (int i = 0; i < result.length; i++) {
                if (result[i] == 0 && result[i + 1] == 0)
                    continue;
                else
                    System.out.print(result[i]);
            }
        } else
            for (int i = 0; i < result.length; i++) {
                if (result[i] == 0 && result[i + 1] == 0)
                    continue;
                else
                    System.out.print(result[i]);
            }
        System.out.println();
    }

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int[] result = new int[50];
        String string1 = getOperand();
        String string2 = getOperand();
        int[] integer1 = convert(string1);
        int[] integer2 = convert(string2);
        String operation;

        System.out.print("Please enter which operation will be used (+ or -): ");
        operation = scan.nextLine();
        if (operation.charAt(0) == '+')
            add(integer1, integer2);
        else if (operation.charAt(0) == '-')
            integer2 = negate(integer2);

        result = add(integer1, integer2);

        System.out.println(Arrays.toString(integer1));
        System.out.println(Arrays.toString(integer2));
        System.out.println(Arrays.toString(add(integer1, integer2)));
        print(result, operation);
    }
}

解决方案

Okay, after so much discussion and so many issues with your code I have totally revised your original code because you said you wanted to learn more. Among other improvements I have done the following changes:

  • Meaninfgul class name
  • Meaningful method and parameter names
  • Convert repeated and often used constants like 50 and the array representation of the number 1 (needed for negation) into static final members for clean code reasons (documentation, easy change in one place, meaningful names), runtime optimisation).
  • Extend the code to permit negative integers as operands
  • Added validation patterns for user input. E.g. now the maximum number length is checked in order to avoid an array overflow.
  • Avoid numeric overflows during calculation by making the array bigger than the maximum number of digits permitted for user input (see source code comments)
  • Add retry loops with error handling for operand and operator input, extract console handling into one parametrised method.
  • Simplify code by removing unnecessary checks because user input is already validated before converting it into an int[].
  • Make debug output optional

package de.scrum_master.stackoverflow;

import java.util.Arrays;
import java.util.Scanner;
import java.util.regex.Pattern;

public class TensComplementArithmetic {
    // Print debug messages?
    private static final boolean DEBUG = true;

    // Maximum length for numbers entered by a user
    // (number of digits excluding the optional +/- sign)
    private static final int MAX_NUMBER_LENGTH = 50;

    // Array must have one additional element for the sign and
    // one more to avoid overflows when adding big negative numbers
    private static final int ARRAY_LENGTH = MAX_NUMBER_LENGTH + 2;

    // Scanner for console input handling
    private static final Scanner INPUT_SCANNER = new Scanner(System.in);

    // Regex pattern for positive/negative integer number format verification incl. length check
    private static final Pattern INTEGER_PATTERN = Pattern.compile("[+-]?[0-9]{1," + MAX_NUMBER_LENGTH + "}");

    // Regex pattern for operator verification (currently only "+"/"-" allowed)
    private static final Pattern OPERATOR_PATTERN = Pattern.compile("[+-]");

    // The number 1 is always needed for converting a 9's into a 10's complement
    // during negation, so we define it as a reusable constant
    private static final int[] NUMBER_ONE;

    static {
        // Initialise constant carrying array representation for number 1
        NUMBER_ONE = new int[ARRAY_LENGTH];
        NUMBER_ONE[ARRAY_LENGTH - 1] = 1;
    }

    public static String readConsoleInput(String prompt, Pattern validationPattern, String errorMessage) {
        String input = null;
        while (input == null) {
            System.out.print(prompt + ": ");
            if (INPUT_SCANNER.hasNext(validationPattern))
                input = INPUT_SCANNER.next(validationPattern);
            else {
                INPUT_SCANNER.nextLine();
                System.out.println(errorMessage);
            }
        }
        return input;
    }

    public static String getOperand(String operandName) {
        return readConsoleInput(
            "Operand " + operandName,
            INTEGER_PATTERN,
            "Illegal number format, please enter a positive/negative integer of max. " + MAX_NUMBER_LENGTH + " digits."
        );
    }

    private static String getOperator() {
        return readConsoleInput(
            "Arithmetical operator (+ or -)",
            OPERATOR_PATTERN,
            "Unknown operator, try again."
        );
    }

    public static int[] parseInteger(String number) {
        char sign = number.charAt(0);
        boolean isNegative = sign == '-' ? true : false;
        if (isNegative || sign == '+')
            number = number.substring(1);

        int[] result = new int[ARRAY_LENGTH];
        int parsePosition = number.length() - 1;
        for (int i = result.length - 1; i >= 0; i--) {
            if (parsePosition < 0)
                break;
            result[i] = number.charAt(parsePosition--) - '0';
        }
        return isNegative ? negate(result) : result;
    }

    public static int[] add(int[] operand1, int[] operand2) {
        int[] result = new int[ARRAY_LENGTH];
        int carry = 0;

        for (int i = ARRAY_LENGTH - 1; i >= 0; i--) {
            result[i] = operand1[i] + operand2[i] + carry;
            if (result[i] >= 10) {
                result[i] = result[i] % 10;
                carry = 1;
            } else
                carry = 0;
        }
        return result;
    }

    public static int[] complement(int[] operand) {
        int[] result = new int[ARRAY_LENGTH];

        for (int i = operand.length - 1; i >= 0; i--)
            result[i] = 9 - operand[i];
        return result;
    }

    public static int[] negate(int[] operand) {
        return add(complement(operand), NUMBER_ONE);
    }

    public static void print(int[] result, String operation) {
        System.out.print(operation.charAt(0) == '-' ? "Difference = " : "Sum = ");
        if (result[0] == 9) {
            result = negate(result);
            System.out.print("-");
        }
        boolean leadingZero = true;
        for (int i = 0; i < result.length; i++) {
            if (leadingZero) {
                if (result[i] == 0)
                    continue;
                leadingZero = false;
            }
            System.out.print(result[i]);
        }
        System.out.println(leadingZero ? "0" : "");
    }

    public static void main(String[] args) {
        int[] operand1 = parseInteger(getOperand("#1"));
        int[] operand2 = parseInteger(getOperand("#2"));
        String operator = getOperator();

        if (operator.equals("-"))
            operand2 = negate(operand2);

        int[] result = new int[ARRAY_LENGTH];
        result = add(operand1, operand2);
        if (DEBUG) {
            System.out.println("Operand #1 = " + Arrays.toString(operand1));
            System.out.println("Operand #2 = " + Arrays.toString(operand2));
            System.out.println("Result     = " + Arrays.toString(result));
        }
        print(result, operator);
    }
}

这篇关于ArrayIndexOutOfBoundsException异常十的补算法实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆