我是编程的初学者,我一直在练习Project Euler编程问题,到目前为止我已经能够做到这一点,但这次我不得不寻求帮助。没有剧透,我试图解决的问题包括找到一个非常大的数字的总和,所以我不能把它保存在int或double中。所以我使用这个方法将两个包含数值的字符串相乘。
private static String multiply(String a, String b) {
// No, I'm not checking if the strings are numeric
int subTotal = 1, extra = 0;
String waitingString = "";
StringBuilder number1 = new StringBuilder(a);
StringBuilder number2 = new StringBuilder(b);
List<String> numbers = new ArrayList<String>();
// The reason I reverse the numbers is the for() loops
// I don't want to count down through the numbers, that
// would just confuse me more.
number1.reverse();
number2.reverse();
for (int i = 0; i < number1.length(); i++) {
waitingString = "";
subTotal = Character.getNumericValue(number1.charAt(i));
for (int j = 0; j < number2.length(); j++) {
subTotal *= Character.getNumericValue(number2.charAt(j));
subTotal += extra;
char[] temp = String.valueOf(subTotal).toCharArray();
waitingString = temp[temp.length - 1] + waitingString;
if (subTotal >= 10 || ((j == number2.length() - 1) && (String.valueOf(subTotal).length() > 1))) {
extra = Integer.parseInt(String.valueOf(subTotal).substring(0, temp.length - 1));
} else {
extra = 0;
}
subTotal = Character.getNumericValue(number1.charAt(i));
}
for (int k = 0; k < i; k++) {
waitingString += "0";
}
waitingString = extra + "" + waitingString;
numbers.add(waitingString);
}
// sumAll() is not the problem just in case you were wondering.
// Because as you've read the code, I'm passing a List<String>
// to it and as I was trying to find the error I printed the list
// before everything to check the values and the error was already
// there, 3 of the values are wrong.
return sumAll(numbers);
}
测试时我自己乘以这个数字:1125899906842624。结果应该是1267650600228229401496703205376.但是我得到的是1267650600228229401607703205376.这是相差111000000000.我一直试图找到错误2天而我只是不能。 我不是在寻找替代或更好的方法来做到这一点,我只是在我的代码中找不到应该添加的错误。 如果您需要查看其余的代码,我可以提供它,请不要介意拼写/语法错误,英语不是我的母语。
答案 0 :(得分:4)
不试图运行它或在调试器下查看它:看起来你正在设置一个extra
变量,这是一个进位,即当你移动时应该添加到下一个产品的值在左边(原始数字,而不是相反的数字)。我可以看到的一个问题是,如果内循环中的 last 产品产生大于或等于10的内容,则计算extra
;但是当你进入下一个外部循环时,extra
仍然具有该值,并且当它不应该被添加到subTotal
时。尝试在外部循环开始时和内部循环开始之前添加语句extra = 0;
。这可能会解决问题。
P.S。通过将subTotal
表示为字符串并使用它,您可以为自己做很多额外的工作。虽然我理解为什么你想为两个被乘数和产品使用字符串,subTotal
是两个单位数的乘积,并且它不会大于89.所以你永远不应该有将其转换为字符串并使用字符串。因此,而不是
char[] temp = String.valueOf(subTotal).toCharArray();
waitingString = temp[temp.length - 1] + waitingString;
你可以说
waitingString = String.valueOf(subTotal % 10) + waitingString;
或类似的东西(subTotal % 10
给出了当subTotal除以10时的余数,因此是subTotal
的最后一位数;而不是用于计算extra
的复杂代码,只需说
extra = subTotal / 10;
除以10并抛弃其余部分。你根本不应该计算String.valueOf(subTotal)
。
PPS。不要担心告诉您使用BigInteger
的答案。如果你正在做一个真正的编程项目,那就是你要使用的。但对于学习如何编程的人来说,我认为编写一个程序来计算两个数字的乘积,这是一个很好的学习工具。
答案 1 :(得分:2)
有人评论说,这可能是BigInteger
班的工作。只是说
BigInteger intA = new BigInteger(a)
BigInteger intB = new BigInteger(b)
然后致电
intA.multiply(intB)
这将为您提供包含结果的BigInteger
。
答案 2 :(得分:1)
我会像这样使用BigInteger
private static String multiply(String a, String b) {
if (a == null || b == null) {
if (b != null) return b;
return a;
}
BigInteger v = new BigInteger(a, 10);
if (v != null) {
BigInteger t = new BigInteger(b, 10);
if (t != null) {
BigInteger r = v.multiply(t);
return r.toString();
}
}
return "";
}
public static void main(String[] args) {
String result = multiply("1125899906842624", "1125899906842624");
String good = "1267650600228229401496703205376";
System.out.println(result.equals(good));
}
运行时打印true
。