2017-07-24 24 views
0
class Hello { 
    public static void main(String args[]) { 
     int i = 10; 
     i *= i++ + i; 
     System.out.println(i); 
    } 
} 

根據運算符優先級,後綴運算符比乘法運算符的優先級更高。括號內的操作數具有更高的優先級。在這個Java程序中,我的邏輯運算符優先級有什麼問題?

第一評價它們:我*(I ++ + I) 所以,現在,它是10 + 11的括號內:我*(21)

i的當前值是11

其次,由於下一個優先級,評估乘法運算符,它不應該是11 * 21 = 231?

雖然,我知道答案是210,爲什麼我上面解釋的邏輯錯誤?

+0

'我現在的價值是11' - 是什麼讓你這麼說? – Mat

+0

@Mat - OP表示,因爲在增加'i'之後它的值確實是11,並且錯誤的假設是這發生在任何其他的'i'操作數被評估之前 –

回答

4

其分解成以下

i = i * (i++ + i); 

現在,您有:

i = 10 * (i++ + i); 

然後,你必須:

i = 10 * (10 + i); 

然後,你必須:

i = 10 * (10 + 11); 

然後,你必須:

i = 10 * (21); 

然後,你必須:

i = 210; 

正如你所看到的,「我」是第一次加載的值,然後計算剩餘的完成,而不是相反。

編輯: 之間的某處,i的值也設置爲11,因此在步驟4中的數字爲「11」,但在此之後,它在最後被覆蓋,所以這個值不再重要。

交換的計算將導致你想要什麼:

i = (i++ + i) * i; 
0

正因爲運營商必須按照特定的順序被應用,並不意味着最高優先級運營商的直接操作數總是要進行評估第一。

事實上,此處適用的規則是:

Java編程語言保證運營商的操作數出現在一個特定的評估順序進行評價,即,由左到右。二元運算符的左側操作數出現前的右側操作數的任何部分evaluated.Jul 23,2011

這可以是非常混亂的,除非你遵循一個簡單的規則進行充分評估:唐不會嵌入子表達式,其副作用在計算過程中會影響操作數,因爲它會使您的代碼無法讀取。

1

這裏首先要注意的是,你不是在做一個簡單的乘法運算,而是使用一個compound assignment operator,它是一個運算符,它封裝了對一個變量執行操作,然後將結果賦值給原始變量。

JLS section about compound assignment operators(如*=):

  • 首先,左邊的操作數進行評估,以產生可變的。如果 此評估突然完成,則由於相同的原因,分配表達式 會突然完成;右邊的操作數不是 評估和沒有分配發生。

  • 否則,保存左側操作數的值,然後評估右側操作數。如果此評估突然完成 ,則分配表達式將以相同的原因突然完成並且不會發生分配。

  • 否則,左側變量的保存值和右側操作數的值用於執行由複合賦值運算符指示的二進制運算。如果此操作突然完成,則由於同樣的原因,賦值表達式會突然完成並且不會發生分配。

突出顯示的文本可以保證在將使用i原始值相乘的左側,即10(而右邊的計算結果爲21,爲你正確地得出了。 )

另一方面,可以說更重要的一點是,算子的優先順序與評價順序不一樣。優先級僅用於將表達式解析到表達式樹中,但運算符總是從左到右和從外部進行求值。

在您的情況下,表達式樹看起來大致如此(請注意最低優先級運算符如何結束了在樹的根部):

*= 
/\ 
    i + 
    /\ 
    i++ i 

...現在它從頂部到底部評估,由左到右是這樣的:

*=   *=   *=   *=  210 
/\  /\  /\  /\ 
    10 + -> 10 + -> 10 + -> 10 21 -> 
    /\  /\  /\ 
    i++ i  10 i  10 11 
+0

我會說*不是*重要的是,因爲如果表達式是'i = i *(i ++ + i)'' –

+0

@MarkAdelsberger結果將是相同的這是一個完全公平的點,但OP一直將它稱爲乘法運算符,它不是。我編輯了我的答案,指出另一個,可以說是更重要的錯誤。 – biziclop

0
int i = 10; 

i *= i++ + i; 
i = i * (i++ +i) 
  • i++將遞增i的值,但返回i在遞增之前保留的原始值。

    i = 10; 
    j = i++; 
    (i is 11, j is 10) 
    
  • 所以,你必須:

    i = 10 * (10 + 11); 
    i = 10 * (21) 
    i = 210 
    
  • 那麼,你的答案是:210

+0

是的,但這並不能捕獲OP所做的推理錯誤。 (我認爲它起初也是如此,但仔細閱讀,那部分是正確的。) –