在Java中,a += a++ * a++ * a++如何计算?

9

我在这个网站上遇到了这个问题,尝试在Eclipse中使用但是不太明白它们是如何被评估的。

    int x = 3, y = 7, z = 4;

    x += x++ * x++ * x++;  // gives x = 63
    System.out.println(x);

    y = y * y++;
    System.out.println(y); // gives y = 49

    z = z++ + z;
    System.out.println(z);  // gives z = 9

根据网站上的评论,x += x++ * x++ * x++ 的值为 x = x+((x+2)*(x+1)*x),经证实是正确的。我认为我对于这个运算符的优先级有所遗漏。

x += 3 * 4 * 5; = 3 + 60 = 63; y = 7 * 7 = 49, z = 4 + 5 = 9x += 3 * 4 * 5; = 3 + 60 = 63; y = 7 * 7 = 49, z = 4 + 5 = 9 - NullUserException
7
为什么这个问题被投票关闭为 C++ 问题的重复? - NullUserException
3
我同意NullUserException的观点 - C/C++在处理这个相同的结构时有不同的规则,但在Java中它是定义良好的,尽管有些丑陋。 - user166390
6个回答

13

Java按照优先级从左到右计算表达式。

int x = 3, y = 7, z = 4;

x (3) += x++ (3) * x++ (4) * x++ (5);  // gives x = 63
System.out.println(x);

y = y (7) * y++ (7);
System.out.println(y); // gives y = 49

z = z++ (4) + z (5);
System.out.println(z);  // gives z = 9

后缀自增运算符只在变量使用/返回后增加变量的值。一切看起来都正确。

这是后缀自增运算符的伪代码:

int x = 5;
int temp = x;
x += 1;
return temp;

来自JLS 15.14.2 (参考文献):

后缀递增表达式的值是在存储新值之前变量的值。


1
谢谢你最后的陈述 :) 让我更容易理解++x是如何被评估的。在这个例子之前,我总是对++x感到困惑。 - WilliamShatner
“Java按照它们的优先级从左到右计算表达式”是一个自相矛盾的说法。Java从左到右计算操作数运算符按照运算符优先级和结合性的顺序进行计算。 - user207421

5

这与运算符优先级本身无关,只与评估顺序有关。

  1. x++ 是后缀递增运算符,因此在评估完之后才会增加 x 的值。
  2. * 先评估右侧表达式再评估左侧表达式。

考虑第2点,可以更具体地将表达式 x++ * x++ * x++ 重写为 x++ * (x++ * (x++))

整个表达式可以写成以下过程:

a = x
x += 1
b = x
x += 1
c = a*b
d = x
x += 1
return c*d

+1,但有一点小问题:实际上,在表达式或语句中只要有多个运算符,就会生效运算符优先级:) 前缀和后缀运算符的优先级高于二元运算符,这就是为什么 x++ * x++ 可以不用括号写出来。你必须写成 (x++) * (x++)。如果没有运算符优先级和括号,只会发生从右到左的运算,它可能意味着 x ++ * (x++)),例如可能是一个语法错误:* 没有 LHS 操作数。 - quetzalcoatl
好的,说得对。我只是想表达答案更多地涉及后缀和前缀运算符的行为,而不是运算符优先级,因为在混合许多不同优先级运算符的表达式中(例如 x++ * x++ + x++ / x++),情况就不同了。 - Tim Bender

2

后缀运算符x++的意思是“给我现在的x值,但将其递增以供将来引用”

因此,根据运算顺序和求值,

x++ * x++ * x++

首先被解释为

3 * 4 * 5(=60)

然后加上原始的3,得到63。

原始值被使用因为它在同一行上,如果你写了像下面这样的内容:

int x = 3;

int y += x++ * x++ * x++; 
x += y;

“x”现在是66,而不是63,因为第二行中的“x”现在是6,而不是原来的3。

2

因为增量操作++是在变量x之后添加的。这是一个后增量操作。这意味着,在处理完操作之后x会被递增。

In your example the expression would be: 
x += 3 * 4 * 5
First the expression is added by 3 (x+=....)
then the first x++ results in 3
the second x++ results in 4 (because it was incremented before)
and the third x++ results in 5.

如果你希望在执行操作之前增加变量的值,你需要写成++x(前缀递增操作)。

1

因为后增量会在取值后修改变量,而+=则会在评估其右侧之前评估其左侧。

x += x++ * x++ * x++; 

变成

tmp0 = x

tmp1 = x
++x
tmp2 = tmp1 * x
++x
tmp3 = tmp2 * x
++x

x = tmp0 + x

你确定左边的表达式会在右边之前被计算吗?因为我认为相反是正确的。 代码分解很好,但最后一条语句x = tmp0 + x对于x = 3不会得出63。 - Ashok Bijoy Debnath
否则它将是66而不是63。 - Dan

1

一元运算符从左到右进行求值,因此第一个x++获取值x,第二个是(x+1),以此类推。而+=根据开始时x的值进行求值,因此会加上x的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接