Java 数学表达式的正确优先级是多少
在Java中,此表达式中数学运算的正确顺序是什么:Java 数学表达式的正确优先级是多少,java,math,operator-precedence,Java,Math,Operator Precedence,在Java中,此表达式中数学运算的正确顺序是什么: a + b * c / ( d - e ) 1. 4 1 3 2 2. 4 2 3 1 我知道两个答案的结果是一样的。但是我想完全理解java编译器的逻辑。本例中首先执行的是什么-乘法还是括号中的表达式?一个指向文档的链接,其中包含了可能会有所帮助的内容 更新:谢谢你们的回答。大多数人认为括号中的表达式是先求值的。在查看Grodriguez提供的参考资料后,我创建了一些测试: int
a + b * c / ( d - e )
1. 4 1 3 2
2. 4 2 3 1
我知道两个答案的结果是一样的。但是我想完全理解java编译器的逻辑。本例中首先执行的是什么-乘法还是括号中的表达式?一个指向文档的链接,其中包含了可能会有所帮助的内容
更新:谢谢你们的回答。大多数人认为括号中的表达式是先求值的。在查看Grodriguez提供的参考资料后,我创建了一些测试:
int i = 2;
System.out.println(i * (i=3)); // prints '6'
int j = 2;
System.out.println((j=3) * j); // prints '9'
有人能解释为什么这些测试会产生不同的结果吗?如果对括号中的表达式进行第一次求值,我希望得到相同的结果-9。正如JeremyP所说,第一个答案是正确的
一般而言,以下规则适用:
- 运算符的每个操作数都在执行操作本身之前进行求值(除了
、|
和&&
?
):
- 操作数从左到右求值。在计算右操作数的任何部分之前,二元运算符的左操作数似乎已被完全计算
- 求值顺序与括号和运算符优先级有关:
- 首先计算括号
- 运算符按优先级顺序计算
- 优先级相等的运算符从左到右求值,但赋值运算符从右到左求值除外
int i = 2;
System.out.println(i * (i=3)); // prints '6'
int j = 2;
System.out.println((j=3) * j); // prints '9'
Add
/\
/ \
a \
Divide
/ \
/ \
/ \
/ \
Multiply Subtract
/\ /\
/ \ / \
b c d e
参考文件:
教程:
我假设您的表达式类似 x=a+b*c/(d-e) 相等运算符具有从右到左的求值顺序。因此,将首先计算=右侧的表达式 如果您参考此优先顺序表: 1) 括号将被计算为(d-e),比如(d-e)=f,因此表达式变成 x=a+b*c/f 2) 现在*和/具有相同的优先级,但求值顺序是从左到右,首先求值的是*,也就是说b*c=g,所以表达式变成了x=a+g/f 3) 现在/具有下一个优先级,因此g/f将被计算为h,因此表达式为x=a+h
4) 最后评估a+h计算结果由定义。所以括号的优先级最高,乘法和除法次之,加减法最低。优先级相等的运算符从左到右求值。因此,问题中的表达式相当于:
a + (b * c) / ( d - e ))
然而,通常所说的“首先被评估”与获得正确答案的运算符优先级之间存在细微差别
在计算“a”之前,不一定实际计算“d-e”。除非表达式中的一个“变量”实际上是一个函数,否则这几乎没有任何区别
运算符优先级的全部要点是将表达式转换为语法树。这里的*
和-
位于树的同一级别。哪一个先被评估与结果无关,也没有理由
编辑:对不起,我被我的C语言背景弄糊涂了。正如其他人所指出的,Java有一个“先计算左手操作数”的规则。将此规则应用于
/
会告诉您,*
首先求值(您的第一个答案)。到目前为止,几乎所有人都将求值顺序与运算符优先级混淆了。在Java中,优先级规则使表达式等效于以下内容:
a + (b * c) / ( d - e )
因为*
和/
具有同等的优先级,并且是左关联的
评估顺序严格定义为(除了| |和&&)。因此,评估的顺序是:
a
b
c
*
d
e
-
/
+
评估的顺序在这一页上。缩进反映了语法树的结构
编辑
针对格罗德里格斯的评论。以下节目:
public class Precedence
{
private static int a()
{
System.out.println("a");
return 1;
}
private static int b()
{
System.out.println("b");
return 2;
}
private static int c()
{
System.out.println("c");
return 3;
}
private static int d()
{
System.out.println("d");
return 4;
}
private static int e()
{
System.out.println("e");
return 5;
}
public static void main(String[] args)
{
int x = a() + b() * c() / (d() - e());
System.out.println(x);
}
}
产生输出
a
b
c
d
e
-5
这清楚地表明乘法是在减法之前执行的 它按以下顺序计算表达式。变量名是需要计算的表达式
a + b * c / (d - e)
2 3 5 6
4 7
1 8
9
那么,你的问题的答案是#1。运算顺序决定了表达式树的形状(树的左边是什么,右边是什么),但总是先计算左边(最后计算根)。在第二个问题中,Java似乎是将括号中的部分作为赋值来计算,而不是数学表达式。这意味着is将不会按照与括号中的操作相同的顺序执行插入式赋值。我想它可能会从左到右进行类似的计算 a+b*c/(d-e) 这可以看作是创建一个表示计算的二叉树,然后从左到右从叶节点开始计算。不幸的是,我的ascii艺术并不伟大,但这里有一个尝试来表示有问题的树:
int i = 2;
System.out.println(i * (i=3)); // prints '6'
int j = 2;
System.out.println((j=3) * j); // prints '9'
Add
/\
/ \
a \
Divide
/ \
/ \
/ \
/ \
Multiply Subtract
/\ /\
/ \ / \
b c d e
我在C#中做了一些测试(我知道这不一样,但这就是我的兴趣所在,测试很容易适应),如下所示:
f = 1;
Console.WriteLine((f=2) + (f) * (f) / ((f) - (f)-1));
Console.WriteLine(2 + 2 * 2 / (2 - 2 - 1));
f = 1;
Console.WriteLine((f) + (f=2) * (f) / ((f) - (f)-1));
Console.WriteLine(1 + 2 * 2 / (2 - 2 - 1));
f = 1;
Console.WriteLine((f) + (f) * (f = 2) / ((f) - (f)-1));
Console.WriteLine(1 + 1 * 2 / (2 - 2 - 1));
f = 1;
Console.WriteLine((f) + (f) * (f) / ((f=2) - (f)-1));
Console.WriteLine(1 + 1 * 1 / (2 - 2 - 1));
f = 1;
Console.WriteLine((f) + (f) * (f) / ((f) - (f=2)-1));
Console.WriteLine(1d + 1d * 1d / (1d - 2d - 1d));
console.writeline语句对是代数语句(使用set a number技巧)和数字表示,显示计算的实际功能。这两对产生的结果彼此相同
可以看出,参数是按顺序计算的,赋值后的参数为2,赋值前的参数为1。所以,事物的评估顺序是从左到右的,我认为,但计算的顺序是你所期望的
我假设这几乎可以用JAVA中的复制粘贴测试来运行
那里,妈妈