我正在编写一个计算器代码,用于解决字符串中给出的输入内容。一切都很好,除非它在括号中得到否定结果时它会严重失败,因为两个操作彼此相邻:
1+2*(10-11) >> 1+2*(-1) >> 1+2*-1
所以* - 在哪里,它在BigDecimal
的构造函数中得到“”(无)。
我知道问题是什么,但我该如何解决呢?
import java.math.BigDecimal;
import java.util.ArrayList;
public class DoMath {
public static void main(String[] args) {
// Test equation goes here.
String number = "95.3+43.23*(10-11.1)";
System.out.println(doMath(number));
}
public static BigDecimal doMath(String input) {
StringBuilder builtInput = new StringBuilder(input);
StringBuilder help = new StringBuilder();
// Check if there are parenthesis in the equation.
boolean noParenthesis = true;
for (int i = 0; i < builtInput.length(); i++) {
if (builtInput.charAt(i) == 40) {
noParenthesis = false;
break;
}
}
if (noParenthesis) { // If there are no parenthesis, calculate the equation!
return calculateAndConvert(builtInput);
} else { // If there are parenthesis, breakdown to simple equations!
int parenthesePair = 0;
// Start extracting characters from the builtInput variable.
for (int i = 0; i < builtInput.length(); i++) {
// Start where we find a parentheses opener.
if (builtInput.charAt(i) == 40) {
parenthesePair = 1;
builtInput.deleteCharAt(i);
for (int j = i; j < builtInput.length(); j++) {
// If we find another opener, add one to parenthesePair variable.
if (builtInput.charAt(j) == 40) {
parenthesePair++;
}
// If we find a closer, subtract one from the given variable.
if (builtInput.charAt(j) == 41) {
parenthesePair--;
}
// If we have found the matching pair, delete it and break the for loop.
if (parenthesePair == 0) {
builtInput.deleteCharAt(j);
builtInput.insert(j, doMath(help.toString()));
break;
}
help.append(builtInput.charAt(j));
builtInput.deleteCharAt(j);
j--;
}
break;
}
}
}
System.out.println(builtInput);
return doMath(builtInput.toString());
}
public static BigDecimal calculateAndConvert(StringBuilder input) {
ArrayList<BigDecimal> listOfNumbers = new ArrayList<BigDecimal>();
StringBuilder numBay = new StringBuilder();
StringBuilder operations = new StringBuilder();
// If the first character is -, the first number is negative.
boolean firstIsNegative = false;
if (input.charAt(0) == 45) {
firstIsNegative = true;
input.deleteCharAt(0);
}
// Converting to numbers.
while (input.length() != 0) {
// If the character is a number or a dot, put it in the numBay variable and delete the char.
if (input.charAt(0) >= 48 && input.charAt(0) <= 57 || input.charAt(0) == 46) {
numBay.append(input.charAt(0));
// If the character is not a number, put it in the operations variable
// and save the number in the list (not operator characters are filtered)
} else {
listOfNumbers.add(new BigDecimal(numBay.toString()));
numBay.setLength(0);
operations.append(input.charAt(0));
}
// Delete the character.
input.deleteCharAt(0);
}
listOfNumbers.add(new BigDecimal(numBay.toString()));
// Setting first number to negative if it's needed.
if (firstIsNegative) {
listOfNumbers.set(0, listOfNumbers.get(0).negate());
}
// Calculate the result from the list and operations and return it.
return calculate(listOfNumbers, operations);
}
public static BigDecimal calculate(ArrayList<BigDecimal> list, StringBuilder ops) {
BigDecimal momentaryResult;
// Check for a multiply operation - if there is one, solve it.
for (int i = 0; i < ops.length(); i++) {
if (ops.charAt(i) == 42) {
momentaryResult = list.get(i).multiply(list.get(i + 1));
list.remove(i);
list.set(i, momentaryResult);
ops.deleteCharAt(i);
i--;
}
}
// Check for a divide operation - if there is one, solve it.
for (int i = 0; i < ops.length(); i++) {
if (ops.charAt(i) == 47) {
momentaryResult = list.get(i).divide(list.get(i + 1));
list.remove(i);
list.set(i, momentaryResult);
ops.deleteCharAt(i);
i--;
}
}
// Check for a subtract operation - if there is one, solve it.
for (int i = 0; i < ops.length(); i++) {
if (ops.charAt(i) == 45) {
momentaryResult = list.get(i).subtract(list.get(i + 1));
list.remove(i);
list.set(i, momentaryResult);
ops.deleteCharAt(i);
i--;
}
}
// Check for a plus operation - if there is one, solve it.
for (int i = 0; i < ops.length(); i++) {
if (ops.charAt(i) == 43) {
momentaryResult = list.get(i).add(list.get(i + 1));
list.remove(i);
list.set(i, momentaryResult);
ops.deleteCharAt(i);
i--;
}
}
// Return with the one remaining number that represents the result.
return list.get(0);
}
}
编辑或者使用不同的算法编写新代码会更容易吗?
答案 0 :(得分:0)
我会将此作为对您问题的评论发布,但我没有这样做的声誉。
无论如何,既然你已经认识到这个错误是“运营商”*-
你不能通过一个减号之前立即替换加号运算符来制定解决这个问题的方法吗?像这样:
1+2*-1
&gt;&gt;&gt; 1-2*1
如果你愿意我可以给你写代码。但是,您可能更容易在已经运行的代码中调整这样的解决方案。
编辑 - 1 :
显然,代码还应该处理以下情况:
1-2*-1
&gt;&gt;&gt; 1+2*1
2*-1
&gt;&gt;&gt; -2*1
编辑 - 2 :
这是我设法制作的代码。如果您发现任何错误,请告诉我。
public int countChar(String str, char chr) {
int count = 0;
for (int k = 0; k < str.length(); k++) {
if (str.charAt(k) == chr)
count++;
}
return count;
}
public String fixBug(String eq) {
boolean hasBug = eq.contains("*-");
if (hasBug) {
String subeq;
int indbug, indp, indm;
eq = eq.replace("*-", "@");
int N = countChar(eq, '@');
for (int k = N; k > 0; k--) {
indbug = eq.indexOf('@');
subeq = eq.substring(0, indbug);
indp = subeq.lastIndexOf('+');
indm = subeq.lastIndexOf('-');
if (indp == -1 && indm == -1) {
eq = "-" + eq;
} else if (indp > indm) {
eq = eq.substring(0, indp) + '-' + eq.substring(indp + 1);
} else {
eq = eq.substring(0, indm) + '+' + eq.substring(indm + 1);
}
}
eq = eq.replace("@", "*");
}
return eq;
}