Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java, "a[1] *= a[1] = b[n + 1]" not working as expected?

So as the title shows, I've got a function that uses a temporary array, and I want to write a value into it from another array, and then multiply the two value with itself.

Example:

float[] a = {0, 0}

a[0] *= a[0] = b[n    ];
a[1] *= a[1] = b[n + 1];

I would expect the above would do the following:

a[0] = b[n    ];
a[0] *= a[0]; //(aka: a[0] = a[0] * a[0])

a[1] = b[n + 1];
a[1] *= a[1];

Though that behavior doesn't seem to be whats happening. Instead it seems just multiply whatever the original value held in "a" was with whatever value was held in "b" like so:

a[0] = a[0] * b[n    ];
a[1] = a[1] * b[n + 1];

It was always my understanding that whatever comes after the "=" is evaluated first, as seen when you do:

float a, b;
a = b = 5;
//"a" and "b" both equal "5" now.

Being that that is the case, would it not show that my original example should work?

Can anyone explain whats going on and why this code doesn't work as intended?

like image 515
Hex Crown Avatar asked Dec 14 '22 17:12

Hex Crown


1 Answers

I think the answers so far are not correct. What comes into play is the evaluation of compound expressions like a *= b. In short, the value of the left hand side is computed before the right hand side. From the JLS (emphasis mine):

At run time, the expression is evaluated in one of two ways.

If the left-hand operand expression is not an array access expression, then:

First, the left-hand operand is evaluated to produce a variable. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason; the right-hand operand is not evaluated and no assignment occurs.

Otherwise, the value of the left-hand operand is saved and then the right-hand operand is evaluated. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.

Otherwise, the saved value of the left-hand variable and the value of the right-hand operand are used to perform the binary operation indicated by the compound assignment operator. If this operation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.

Otherwise, the result of the binary operation is converted to the type of the left-hand variable, subjected to value set conversion (§5.1.13) to the appropriate standard value set (not an extended-exponent value set), and the result of the conversion is stored into the variable.

In your example:

a[0] *= a[0] = b[n    ];
  1. value of a[0] is computed and stored in say tmp
  2. a[0] = b[n] is evaluated, giving the value of b[n] (and changing the value of a[0] to b[n])
  3. tmp * a[0] is computed
  4. the result of the last step is assigned to a[0]

So, what you get is effectively a[0] *= b[n].

EDIT: About the confusion about right-to-left-evaluation of assignments: I did not find that terminology used in the JLS, and IMHO it is not correct (although it is used in the Java tutorials). It is called right-**associative* assThe JLS says this about assignments:

There are 12 assignment operators; all are syntactically right-associative (they group right-to-left). Thus, a=b=c means a=(b=c), which assigns the value of c to b and then assigns the value of b to a.

like image 194
Axel Avatar answered Dec 16 '22 08:12

Axel