我正在研究Project Euler Problem 9,其中指出:
毕达哥拉斯三元组是一组三个自然数,a< b< c,为此,a^2 + b^2 = c^2
例如,3 ^ 2 + 4 ^ 2 = 9 + 16 = 25 = 52。
恰好存在一个毕达哥拉斯三重态,其中a + b + c = 1000。 找到产品abc。
这是我到目前为止所做的:
class Project_euler9 {
public static boolean determineIfPythagoreanTriple(int a, int b, int c) {
return (a * a + b * b == c * c);
}
public static void main(String[] args) {
boolean answerFound = false;
int a, b, c;
while (!answerFound) {
for (a = 1; a <= 1000; a++) {
for (b = a + 1; b <= 1000; b++) {
c = 1000 - a - b;
answerFound = determineIfPythagoreanTriple(a, b, c);
}
}
}
System.out.println("(" + a + ", " + b + ", " + c + ")");
}
}
当我运行我的代码时,我收到此错误:
Project_euler9.java:32: error: variable a might not have been initialized
System.out.println("The Pythagorean triplet we're looking for is (" + a + ", " + b + ", " + c + ")");
注意:我的每个变量(a,b和c)都有不同的行号。
我认为当我将a,b和c声明为整数时,如果未分配,默认值为0。
即使不是这种情况,它看起来像是他们所有做都被分配了,所以我对这个错误感到有点困惑。
为什么会这样?
答案 0 :(得分:7)
实例变量(在您的情况下,它们将是整数)被分配给0
为默认值。局部变量不。 (From Java Docs)
如果未输入循环,则您的变量不会被初始化,这是导致错误的原因。
您可以做的是在声明时初始化:
int a=0, b=0, c=0;
答案 1 :(得分:5)
你的问题就在这一行:
System.out.println("(" + a + ", " + b + ", " + c + ")");
位于while (!answerFound) {...}
循环之后。编译器认为可能存在一个或多个变量a
,b
或c
未初始化的情况。
使用此行:
int a=0, b=0, c=0;
在声明变量时,以便在声明时初始化它们,并且错误应该消失。
答案 2 :(得分:3)
在声明局部变量之后,在方法的开头执行此操作:
a = b = c = 0;
该错误基本上表明Java无法确定变量在到达System.out.println()
时是否分配了值。请记住:在Java中,只有属性具有默认值,所有局部变量必须在某些时候显式初始化。
答案 3 :(得分:3)
你的想法是对的:
你在哪里:
你错了:
供参考,请查看The docs:
默认值
声明字段时并不总是需要指定值。 声明但未初始化的字段将设置为a 编译器合理默认。一般来说,这个默认值 将为零或null,具体取决于数据类型。依靠这样的 但是,默认值通常被认为是错误的编程 风格。
下表总结了上述数据的默认值 类型。
数据类型默认值(对于字段)
字节0
短0 int 0
长0L
浮点数0.0f
double 0.0d
char'\ u0000'
字符串(或任何对象)null
布尔值假局部变量略有不同;编译器永远不会分配 默认值为未初始化的本地变量。如果不能 初始化声明它的局部变量,确保 在尝试使用它之前为其赋值。访问 未初始化的局部变量将导致编译时错误。
答案 4 :(得分:1)
在方法中声明local variables
时,必须在使用它们之前为它们分配值。
答案 5 :(得分:1)
必须确信Java编译器在我们到达HERE
行时,可以证明a
,b
和c
已设置为某种内容:
boolean answerFound = false;
int a, b, c;
while (!answerFound) {
for (a = 1; a <= 1000; a++) {
for (b = a + 1; b <= 1000; b++) {
c = 1000 - a - b;
answerFound = determineIfPythagoreanTriple(a, b, c);
}
}
}
// HERE
从编译器的角度来看,如果循环执行了零次,那么它将在没有变量初始化的情况下到达HERE
;因此,你不能使用它们。 我们知道这是不可能的,因为我们知道answerFound
已初始化为false
,因此循环将至少执行一次,并且每个{{1} }循环至少执行一次。但是语言必须有一致的规则来确定哪些程序合法,哪些程序不合法;为了避免过于复杂,编译器不需要进行必要的推断,以证明始终初始化for
,a
和b
。我没有详细看过实际的“明确分配”规则,但我认为它们已经相当复杂了。
所以即使你知道变量将被初始化,你也无法说服编译器。因此,只要在声明它们时初始化它们。
c
顺便说一下,由于int a = 0, b = 0, c = 0;
在之外 while
次循环,当for
变为answerFound
时,此代码不会立即退出。它仍然执行true
循环直到它们完成,然后才进行测试以查看是否离开for
循环。你需要解决这个问题。
P.S。如果你想作弊,请注意每个毕达哥拉斯三元组的形式为 a = m 2 - n 2 , b = 2mn < / em>, c = m 2 + n 2 ,对于某些 m 和 n 。实际上,你可以在没有计算机的情况下使用代数得到答案。但是继续完成你开始的课程 - 这是很棒的练习。
答案 6 :(得分:0)
正如其他人所指出的那样,到a, b, c
时,您的变量System.out.println
可能尚未初始化。有几种方法可以避免这种情况。
初始化变量显式,所以:
int a = 0;
使用 do ... while 循环,确保循环至少运行一次,所以:
do {
[...]
} while (!answerFound);
使用循环范围的变量,避免使用本地范围的变量,因此:
for (int a = 1; a <= 1000; a++) {
[...]
}