Incrementor logic

后端 未结 7 2122
醉梦人生
醉梦人生 2020-11-27 05:37

I\'m trying to get deeper with post and pre incrementors but am a bit stuck with the following expression :

public static void main(String[] args) {
    int i         


        
相关标签:
7条回答
  • 2020-11-27 05:48

    Ok, let's break down every thing:

    int i = 0; // i = 0, no big deal
    

    Then starting into the most inner parenthesis:

    (i+=2 + --i)
    
    • it first decrement i and use the result (-1)
    • then add 2 (-1+2=1)
    • and add the result to i (which is 0 at the start of the operation) (0+1=1=i)

    At the end, the first decrement is ignored by the reassignation.

    Next parenthesis:

    i+= (++i + previous_result - ++i)
    
    • it increase the i ( with ++i) at two points
    • then the operation becomes (i+1) + previous_result - (i+2) (notice how the increment are not simultaneous) that gives 2 + 1 - 3 = 0.
    • the result of the operation is added to the initial i (0)

    Again the increment will get discard by the reassignation.

    finally:

    i = previous_result
    

    Which gives 0 :)

    0 讨论(0)
  • 2020-11-27 05:49

    Paranthesis takes the precedence. order would be from inner most to outermost

    (i+=2 + --i) =>i=i+=2==(2) --2 =0 
    (++i - ++i)  =>1-1=0 
    i=i+ =0+0 =0
    

    Each expression evaluates to 0

    0 讨论(0)
  • 2020-11-27 05:50

    Because of the highest precedence (...) will be evaluated first then ++ & -- and then remaining operators. Your expression is like

    i = i += ( (++i) + (i+=2 + (--i)) - (++i) );
    
    //i = i = i + ( (++i) + (i+=2 + (--i)) - (++i) );
    //i = i = 0 + ( (++i) + (i+=2 + (--i)) - (++i) );
    //i = i = 0 + ( (1) + (i+=2 + (--i)) - (++i) );
    //i = i = 0 + ( (1) + (i+=2 + (0)) - (++i) );
    //i = i = 0 + ( (1) + (2 + (0)) - (++i) );
    //i = i = 0 + ( (1) + (2) - (++i) );
    //i = i = 0 + ( (1) + (2) - (3) );
    //i = i = 0 + ( 3 - 3 );
    //i = i = 0 + ( 0 );
    //i = 0
    

    Please fully parenthesize your expression. You will understand evaluation order of expression.

    For your EDIT 1

    i = i+=( (++i) + (i+=32500 + (--i) ) - (++i) ); 
    
    // 0 + ( (++i) + (i+=32500 + (--i) ) - (++i) ); // i = 0
    // 0 + ( (1) + (i+=32500 + (--i) ) - (++i) );  // i = 1
    // 0 + ( (1) + (i+=32500 + (0) ) - (++i) ); // i = 0
    // 0 + ( (1) + (32500 + (0) ) - (++i) );  // i = 32500
    // 0 + ( (1) + (32500) - (++i) ); // i = 32500
    // 0 + ( (1) + (32500) - (32501) ); // i = 32501
    // 0 + ( 32501 - 32501 ); // i = 32501
    // 0 // i = 0
    
    0 讨论(0)
  • 2020-11-27 06:00

    I suggest the following: format the code differently, so that there's only 1 statement per line, e.g.

    @Test
    public void test() {
        int i = 0;
        i = 
        i+=
        (
        ++i 
        + 
        (
        i+=
        2 
        + 
        --i
        ) 
        -
        ++i
        );
        System.out.println(i); // Prints 0 instead of 5
    }
    

    Then run it under the debugger and press F5 ("Step into") always. This will help you to understand in which order items get evaluated:

    1. int i=0;
    2. i=: ... (needs to wait for result of calculation A)
    3. i+= ... (needs to wait B)
    4. ++i: i=1
    5. i+= ... (needs to wait C)
    6. 2+
    7. --i: i=0
    8. ...: i=3 (result for wait C)
    9. -
    10. ++i: i=4 and operand of - is also 4
    11. ...: i=0 (result for wait B)
    12. ...: i=0 (result for wait A)

    Line 10 will always make the result of line 3 0, so the initial value of i will never be changed by the whole operation.

    0 讨论(0)
  • 2020-11-27 06:05

    This is the logic taking into account your first edit (with an unknown X):

    public static void main(String[] args) {
        int i = 0;
        i = i+=(++i + (i+=X + --i) - ++i);
        // i = 0 += (++i + ((i += (X + --i)) - ++i));
        // i = 0 += (1 + ((i += (X + --i)) - ++i)); // i = 1
        // i = 0 += (1 + ((1 += (X + --i)) - ++i)); // i = 1 and i will then take the result of 1 += (X + --i)
        // i = 0 += (1 + ((1 += (X + 0)) - ++i)); // i = 0 and i will then take the result of 1 += (X + 0)
        // i = 0 += (1 + (X + 1 - ++i)); // i = X + 1
        // i = 0 += (1 + (X + 1 - X - 2)); // i = X + 2
        // i = 0 += (0); // i = X + 2
        // i = 0;
        System.out.println(i); // Prints 0
    }
    

    Tricks here:

    • += is an assignement operator so it is right-associative: in the snippets, I added parenthesis to express this more clearly
    • The result of the assignment expression is the value of the variable after the assignment has occurred
    • The postfix increment operator ++ and postfix decrement operator -- add or subtract 1 from the value and the result is stored back into the variable.
    • The + additive operator first computes the left-hand operand then the right-hand operand.

    For your second edit (with an unknown I added):

    public static void main(String[] args) {
        int i = I;
        i = i+=(++i + (i+=X + --i) - ++i);
        // i = I += (++i + ((i += (X + --i)) - ++i));
        // i = I += (I+1 + ((i += (X + --i)) - ++i)); // i = I+1
        // i = I += (I+1 + ((I+1 += (X + --i)) - ++i)); // i = I+1 and i will then take the result of I+1 += (X + --i)
        // i = I += (I+1 + ((I+1 += (X + I)) - ++i)); // i = I and i will then take the result of I+1 += (X + I)
        // i = I += (I+1 + (X+2*I+1 - ++i)); // i = X + 2*I + 1
        // i = I += (I+1 + (X+2*I+1 - X-2*I-2)); // i = X + 2*I + 2
        // i = I += (I); // i = X + 2*I + 2
        // i = 2 * I;
        System.out.println(i); // Prints 2 * I
    }
    
    0 讨论(0)
  • 2020-11-27 06:06

    Quoting Java Language Specification, 15.7 Evaluation Order:

    The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.

    The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.

    If the operator is a compound-assignment operator (§15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied binary operation.

    So, essentially, i += ++i will remember the old value of i on the left side, before evaluating the right side.

    Remember, evaluation order of operands and precedence of operators are two different things.

    Showing evaluation order, step by step, with saved value in {braces}:

    int i = 0;
    i    = i    += (++i + (i    += 2 + --i) - ++i); // i = 0
    i{0} = i    += (++i + (i    += 2 + --i) - ++i); // i = 0
    i{0} = i{0} += (++i + (i    += 2 + --i) - ++i); // i = 0
    i{0} = i{0} += (1   + (i    += 2 + --i) - ++i); // i = 1
    i{0} = i{0} += (1   + (i{1} += 2 + --i) - ++i); // i = 1
    i{0} = i{0} += (1   + (i{1} += 2 + 0  ) - ++i); // i = 0
    i{0} = i{0} += (1   + (i{1} += 2      ) - ++i); // i = 0
    i{0} = i{0} += (1   + 3                 - ++i); // i = 3
    i{0} = i{0} += (4                       - ++i); // i = 3
    i{0} = i{0} += (4                       - 4  ); // i = 4
    i{0} = i{0} += 0                              ; // i = 4
    i{0} = 0                                      ; // i = 0
    0                                             ; // i = 0
    

    Followup to edits to question

    If we name the initial value I and the constant N:

    int i = I;
    i = i += (++i + (i += N + --i) - ++i);
    

    Then we can see that the values are:

    i{I} = i{I} += ((I+1) + (i{I+1} += N + I) - ((I+1+N+I)+1));
    i{I} = i{I} += (I + 1 + (I + 1 + N + I) - (I + 1 + N + I + 1));
    i{I} = i{I} += (I + 1 + I + 1 + N + I - I - 1 - N - I - 1);
    i{I} = i{I} += I;
    i{I} = I + I;
    i = 2 * I;
    
    0 讨论(0)
提交回复
热议问题