我试图在Netbeans上使用Java解决复杂的数学表达式,但是我有两个问题:“找不到符号(变量)”,并且得到的结果始终是“ NaN”。
但是当我尝试'double x = 0;'时而不是'double x;'我的代码有效,但我得到的答案始终是“ NaN”。我还尝试在扫描'double x = scan.nextDouble();'上初始化变量。但它也不起作用。
然后,我意识到我键入的大多数涉及复杂数学的代码都需要具有“ = 0;”的模式。用于由编译器找到的变量。
所以我真正的问题是,'double x = 0;'有什么区别?和“ double x;”为什么前者在数学表达式中起作用,而编译器无法检测到后者?
下面不必要的信息
//The code I made for my homework
double ans, num, den, x, y;
//double x = 0;
//double y = 0;
//variable x and y might not have been initialized
num = Math.cbrt( ((2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y,4) )) );
den = (4 * x * Math.pow(y, ((2 * x) + (2 * y))));
ans = num / den;
System.out.print("x: ");
x = scan.nextDouble();
System.out.print("y: ");
y = scan.nextDouble();
System.out.println("\n The answer is " + ans);
我的数学表达式为((\ root(3)((2x ^(4)y + 2xy ^(4)))))/(4xy ^(2x + 2y))
我希望
的输出x:2 y:3
答案是0.096157 ...
相反,我得到的结果是“变量x和y可能尚未初始化”,而在另一种情况下,我得到的结果是“答案为NaN”。我在想是否可以为每个术语使用变量来解决它。
编辑:我成功地完成了“双倍”的划分 通过删除“ double x = 0;”,我消除了 “ NaN”。相反,我同时声明并为变量赋值。
System.out.print("x: ");
double x = scan.nextDouble();
System.out.print("y: ");
double y = scan.nextDouble();
//preparation
//double term1, term2, term3, term4, term5, term6, exp; //x, y;
//double x = 0;
//double y = 0;
//variable x and y might not have been initialized
//double term1 = (Math.cbrt(2 * Math.pow(x,4) * y));
//double term2 = (Math.cbrt(2 * x * Math.pow(y,4)));
//double term3 = (4 * x);
//double term4 = (2 * x);
//double term5 = (2 * y);
// double exp = term4 + term5;
//double term6 = (Math.pow(y,exp));
//double num = (Math.cbrt((2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y, 4))));
//double den = term3 * term6;
double num = (2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y,4) );
double den = (4 * x * Math.pow(y, ((2 * x) + (2 * y))));
double ans = Math.cbrt(num / den);
System.out.println("\n The answer is " + ans);
答案 0 :(得分:1)
在引用局部变量之前,必须为其赋值。由于您的代码是从上到下执行的,因此将在 x
和y
初始化为用户输入值之前进行计算。这就是为什么在您的计算中显示“变量可能未初始化”的原因。
您的误解可能是因为这些行定义了x
,y
,num
,den
之间的某种“关系”:
num = Math.cbrt( ((2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y,4) )) );
den = (4 * x * Math.pow(y, ((2 * x) + (2 * y))));
ans = num / den;
但是实际上他们没有。他们只是简单地进行计算,并将左侧的变量设置为结果。但是,此时x
和y
的值尚不知道,因为x = ...
和y = ...
行还没有运行。
如果在顶部添加double x = 0
和double y = 0
怎么办?那解决了编译器错误。现在可以执行计算,但是它将使用x = 0和y = 0。这就是它当时获得的所有信息,因为尚未获得用户输入的行。
您应该做的是在计算之前移动读取用户输入的行:
System.out.print("x: ");
x = scan.nextDouble();
System.out.print("y: ");
y = scan.nextDouble();
num = Math.cbrt( ((2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y,4) )) );
den = (4 * x * Math.pow(y, ((2 * x) + (2 * y))));
ans = num / den;
System.out.println("\n The answer is " + ans);
此外,要获得预期的输出0.096157 ...,您需要将立方根应用于整个分数,而不仅仅是分子:
num = (2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y,4) );
den = (4 * x * Math.pow(y, ((2 * x) + (2 * y))));
ans = Math.cbrt(num / den);
答案 1 :(得分:1)
所以我真正的问题是
double x = 0;
和double x;
之间有什么区别
前者声明x
并为其提供初始值。
后者声明x
且未赋予其初始值。您可以稍后给x
赋一个值,但是您必须 对导致该变量使用的所有路径进行此操作。例如:
double x;
if (Math.pow(2, 2) >= 0.0) {
x = 0.0;
} else {
x = 1.0;
}
System.out.println(x); // OK
与
double x;
if (Math.pow(2, 2) >= 0.0) {
x = 0.0;
}
System.out.println(x); // ERROR
后者是编译错误,因为在初始化之前,可能存在遍历代码的路径,x
可以在其中使用。
现在任何具有高中数学知识的人都可以告诉您,整数的平方将始终大于或等于零,因此将永远不会使用else
分支。但是Java编译器不知道这一点,并且会给您一个编译错误。 (实际上,不允许 不会给您一个编译错误。我不会赘述:如果您愿意,它们位于JLS中。)
为什么前者在数学表达式中起作用,而编译器无法检测到后者?
现在这是一个有趣的问题。
答案是=
在编程语言和数学方程式中具有根本不同的含义。
在Java之类的编程语言中,a = b;
的意思是“将a
的当前值分配(设置)为b
的当前值”。
在数学方程式中,a = b
的意思是“对于使用这些 a
和b
变量的所有位置,a
的值都是等于b
的值。”。基本上,这是对a
和b
的可能值的限制。
对此进行思考的另一种方式是,在数学中,方程式中的变量代表一组可能的值。该方程约束值的集合;例如a = sqrt(4)
相当于说a
表示 {x | x * x == 4}
,它与集合{-2, +2}
相同。
现在,数学确实存在表示法错误的情况。例如a = a + 1
相当于说a
表示 {x | x == x + 1}
...,它是空集。
(我上面使用的符号不是人们通常会使用的古典数学家和形式方法。不幸的是,除非您修过某些大学水平的数学学科/单元,否则很难解释这一点。计算机科学课程的学习单元。)
最后,这是解决您其他编译和运行时错误的通用问答:
答案 2 :(得分:0)
包括基元在内的局部变量没有分配默认值,需要显式初始化。 您必须为x和y设置初始值,否则编译器会提出抗议。
Why must local variables, including primitives, always be initialized in Java?