【问题标题】:Addition and Subtraction of large ints without Math.BigInteger没有 Math.BigInteger 的大整数的加法和减法
【发布时间】:2017-03-03 17:45:20
【问题描述】:

好的,所以我被分配了一个使用堆栈的练习。这个任务的挑战是创建一个程序,可以在不使用任何库或导入(例如,没有 BigInteger)的情况下添加和减去非常大的整数(可能是无限大小)。

这就是我处理加法的方式:


public Stack<Integer> sum(Stack<Integer> leadingStack, Stack<Integer> secondStack) {
    int carry = 0;
    Stack<Integer> resultStack = new Stack<Integer>();
    while (leadingStack.isEmpty() == false && secondStack.isEmpty() == false) {
        int result = 0;
        int dig1 = leadingStack.pop();
        int dig2 = secondStack.pop();
        int resultDig = 0;

        result = dig1 + dig2 + carry;
        resultDig = result % 10;
        carry = result / 10;
        resultStack.push(resultDig);
    }
    if (carry > 0)
        resultStack.push(carry);
    return resultStack;
}

此方法似乎适用于某些整数,而不适用于其他整数。例如,如果我输入 500 和 450,我会按预期得到 950。但是,如果我输入 500 和 45,我会得到 45。


这就是我处理减法的方法(非常相似的方法):


    public Stack<Integer> sub(Stack<Integer> leadingStack, Stack<Integer> secondStack) {
    boolean borrow = false;
    Stack<Integer> resultStack = new Stack<Integer>();
    while (leadingStack.isEmpty() == false && secondStack.isEmpty() == false) {
        int dig1 = leadingStack.pop();
        int dig2 = secondStack.pop();
        if (borrow = true) {
            dig1 -= 1;
            borrow = false;
        }
        if (dig1 - dig2 < 0) {
            dig1 += 10;
            resultStack.push(dig1 - dig2);
            borrow = true;
        }
    }
    return resultStack;
}

这有一个非常相似的问题。例如,如果我减去 50 和 45,我得到 4。如果我减去 50,000 和 45,000,我得到 4,900。


我确定我在这里遗漏了一些简单的东西,但我一遍又一遍地查看代码,我不确定它是什么。

【问题讨论】:

  • 一次只关注一个部分。使用调试器单步调试代码并查看每一步的变量值。调试是一项重要的技能,只能通过实践来学习。
  • 密切关注您的 add() 方法如何处理不同位数的数字。
  • 你在使用java.util.Stack时不是在“使用库”吗?
  • 没有必要使用 == 来比较布尔值,因为结果是一个你已经开始的布尔值。 x == truex 相同。 x == false!x 相同。
  • 还要确保您知道 = 和 == 之间的区别。

标签: java stack biginteger addition subtraction


【解决方案1】:

您的代码中有几个地方需要注意:

  • 如果堆栈的大小不同,则不会处理较大堆栈的剩余部分
  • 返回结果堆栈时,其元素必须颠倒,因为最小的位置数字首先被压入(更大的位置最后被压入)
  • if (borrow = true) 处具有相等性的混合赋值运算符
  • 减法方法不处理负数

全部在代码中:

public Stack<Integer> sum(Stack<Integer> leadingStack, Stack<Integer> secondStack) {
  int carry = 0;
  Stack<Integer> resultStack = new Stack<Integer>();
  while (leadingStack.isEmpty() == false && secondStack.isEmpty() == false) {
    int dig1 = leadingStack.pop();
    int dig2 = secondStack.pop();
    int result = dig1 + dig2 + carry;
    int resultDig = result % 10;
    carry = result / 10;
    resultStack.push(resultDig);
  }

  Stack<Integer> leftStack = leadingStack.isEmpty() ? secondStack : leadingStack;
  while (leftStack.isEmpty() == false) {
    int dig = leftStack.pop();
    if (carry > 0) {
        dig += carry;
        carry = 0;
    }
    resultStack.push(dig);
  }

  if (carry > 0) resultStack.push(carry);
  return reverse(resultStack);
}

public Stack<Integer> sub(Stack<Integer> leadingStack, Stack<Integer> secondStack) {
  boolean borrow = false;
  Stack<Integer> resultStack = new Stack<Integer>();

  if (leadingStack.size() < secondStack.size()) {
    // Handle negative number
  }
  while (leadingStack.isEmpty() == false && secondStack.isEmpty() == false) {
    int dig1 = leadingStack.pop();
    int dig2 = secondStack.pop();
    if (borrow) {
        dig1 -= 1;
        borrow = false;
    }
    if (dig1 < dig2) {
        dig1 += 10;
        resultStack.push(dig1 - dig2);
        borrow = true;
    }
    else {
        resultStack.push(dig1 - dig2);
    }
  } 

  Stack<Integer> leftStack = leadingStack.isEmpty() ? secondStack : leadingStack;
  while (leftStack.isEmpty() == false) {
    int dig = leftStack.pop();
    if (borrow) {
      dig -= 1; 
      borrow = false;
    }
    resultStack.push(dig);
  }

  if (borrow) {
    // Handle negative number
  }
  return reverse(resultStack);
}

private Stack<Integer> reverse(Stack<Integer> inStack) {
  Stack<Integer> outStack = new Stack<>();
   while (inStack.isEmpty() == false) outStack.push(inStack.pop());
   return outStack;
}

【讨论】:

  • 谢谢!这些都是我的代码明显的问题。我实现了代码的 leftStack 部分,一切看起来都很好。我不确定我是如何忘记处理每个堆栈的不同大小的。
  • @Quinn 你能告诉大家你是如何处理负数的吗?
【解决方案2】:

我会开始看看这种情况:

while (leadingStack.isEmpty() == false && secondStack.isEmpty() == false)

这意味着“当两个堆栈都不为空时”。但是如果你有 2 个不同位数的数字(比如说 500 和 45),它会失败(因为一个堆栈将为空,另一个不会,在处理所有数字之前离开循环)。所以你应该将条件更改为“至少一个堆栈不为空”:

while (leadingStack.isEmpty() == false || secondStack.isEmpty() == false)

另一个提示:isEmpty() 返回一个布尔值,您无需使用== 进行比较,您可以这样做:

while (! leadingStack.isEmpty() || ! secondStack.isEmpty())

请注意,由于一个堆栈可能是空的而另一个不是,您应该在调用 pop 之前检查它是否为空:

int dig1 = 0;
if (!leadingStack.isEmpty()) {
    dig1 = leadingStack.pop();
}
int dig2 = 0;
if (!secondStack.isEmpty()) {
    dig2 = secondStack.pop();
}

【讨论】:

  • 不要将布尔值与布尔文字进行比较以获得布尔值,因为只有布尔值就足够了。
  • @LewBloch 我也在答案中解释了这一点
  • 是的,你做到了。对不起,冗余。
猜你喜欢
  • 2018-10-10
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-25
  • 1970-01-01
相关资源
最近更新 更多