数学表达式的正确优先级是什么

时间:2010-10-26 12:33:28

标签: java math operator-precedence

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。

8 个答案:

答案 0 :(得分:13)

由于JeremyP很好shown us,第一个答案是正确的。

通常,以下规则适用:

  • 在执行操作本身之前评估运算符的每个操作数(||&&? :除外)
  • 操作数从左到右进行评估。在评估右侧操作数的任何部分之前,二元运算符的左侧操作数似乎已完全评估。
  • 评估顺序遵循括号和运算符优先级:
    • 首先评估括号。
    • 按优先顺序评估运算符。
    • 具有相同优先级的运算符从左到右进行计算,但从右到左计算的赋值运算符除外。

请注意,前两个规则解释了第二个问题的结果:

int i = 2;
System.out.println(i * (i=3)); // prints '6'
int j = 2;
System.out.println((j=3) * j); // prints '9'

参考文档:

http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#4779

教程:

http://download.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

答案 1 :(得分:10)

到目前为止,几乎所有人都将评估顺序与运营商优先级混为一谈。在Java中,优先规则使表达式等效于以下内容:

a + (b  * c) / ( d - e )

因为*/具有相同的优先级并且是左关联的。

评估顺序严格定义为left hand operand first, then right, then operation(||和&&)除外。所以评估的顺序是:

  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

清楚地表明在减法之前执行乘法

答案 2 :(得分:4)

按以下顺序评估表达式。变量名是需要评估的表达式。

a + b * c / (d - e)
    2   3    5   6
      4        7
1         8
  9

所以,你的问题的答案是#1。操作顺序决定表达式树的形状(树的左侧是什么,右侧是什么),但是始终首先评估左侧(最后评估根)。

答案 3 :(得分:1)

我认为它可能会从左到右评估这样的评估。

A + B * C /(d-e)中

Action           Left Value      Right Value
Start Add        a               b*c/(d-e)
Start Multiply   b               c
Calc Multiply (since it can)    
Start Divide     b*c             (d-e)
Start Subtract   d               e
Calc Subtract
Calc Divide
Calc Add

这可以被认为是创建一个表示计算的二叉树,然后从叶子节点开始,从左到右,计算事物。不幸的是,我的ascii艺术不是很好,但这里是尝试代表有问题的树:

   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数字技巧)和显示计算实际执行的数字表示。这些对产生的结果相同。

可以看出,参数按顺序进行评估,其中任何一个在赋值为2之后和之前为1。因此,事物的评价顺序从左到右是简单的,但我认为计算的顺序与你期望的一样。

我认为这几乎可以通过复制和粘贴来运行,以便在JAVA中进行测试...

这里可能有一些未被注意的假设,所以如果有人确实发现了这里的逻辑缺陷,请打电话给我,我会完成它们。

答案 4 :(得分:0)

我假设你的表达式会像

x = a + b * c /(d - e)

等式运算符具有从右到左的评估顺序。因此,将首先评估=右侧的表达式。

如果您参考此优先级图表:http://www.java-tips.org/java-se-tips/java.lang/what-is-java-operator-precedence.html

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

答案 5 :(得分:0)

在你的第二个问题中,似乎Java正在将括号中的部分作为赋值进行评估,而不是数学表达式。这意味着不会以与括号中的操作相同的顺序执行括号分配。

答案 6 :(得分:-1)

计算结果由Operator Order of Precedence定义。所以括号在这里具有最高优先级,乘法和除法次高,加法和减法最低。具有相同优先级的运算符从左到右进行计算。所以问题中的表达式相当于:

    a + (b  * c) / ( d - e ))

然而,“首先评估”的正常含义与获得正确答案的运算符优先级之间存在细微差别。

“d-e”不一定在计算“a”之前实际计算。除非表达式中的一个“变量”实际上是一个函数,否则这几乎没有任何区别。 The Java standard does not specify the order of evaluation of components of an expression.

答案 7 :(得分:-1)

a + b * c / ( d - e )
      1         1
          2
  3

运算符优先级的重点是将表达式转换为语法树。这里*-位于树的同一级别。首先评估哪一个与结果无关,并且不保证

编辑:抱歉,我对我的C背景感到困惑。正如其他人所指出的那样,Java有一个“评估左手操作数优先”的规则。将此规则应用于/会告诉您首先评估*(您的第一个答案)。