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

在Java中,此表达式中数学运算的正确顺序是什么:

    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中的复制粘贴测试来运行

那里,妈妈