8

Tôi đã gặp vấn đề này in this website và đã thử nó trong Eclipse nhưng không thể hiểu chính xác chúng được đánh giá như thế nào.a + = a ++ * a ++ * a ++ trong Java. Làm thế nào để nó được đánh giá?

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 

Theo một bình luận trên trang web, x + = x ++ * x ++ * x ++ giải quyết để x = x + ((x + 2) * (x + 1) * x) mà hóa ra là sự thật. Tôi nghĩ rằng tôi đang thiếu một cái gì đó về điều này ưu tiên nhà điều hành.

+0

'x + = 3 * 4 * 5; = 3 + 60 = 63'; 'y = 7 * 7 = 49',' z = 4 + 5 = 9' – NullUserException

+6

Tại sao điều này lại được bình chọn là trùng lặp với câu hỏi C++? – NullUserException

+2

(Tôi đồng ý với NullUserException - C/C++ có * quy tắc * khác nhau để xử lý cùng cấu trúc này, nhưng nó sẽ được xác định rõ ràng dưới Java, nếu không xấu.) –

Trả lời

12

Biểu thức đánh giá Java từ trái sang phải & theo mức độ ưu tiên của chúng.

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 

Toán tử tăng thêm sau tăng biến sau khi biến được sử dụng/trả về. Tất cả có vẻ đúng.

Đây là giả cho các nhà điều hành tăng postfix:

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

Từ JLS 15.14.2 (reference):

The value of the postfix increment expression is the value of the variable before the new value is stored.

+1

Cảm ơn câu cuối cùng :) làm cho nó dễ dàng để hiểu cách ++ x được đánh giá. Luôn luôn bị nhầm lẫn với ++ x trước ví dụ này. – WilliamShatner

+0

'Java đánh giá các biểu thức từ trái sang phải theo ưu tiên của chúng' là một mâu thuẫn về mặt ngữ nghĩa. Java đánh giá * toán hạng * từ trái qua phải; * toán tử * được đánh giá theo thứ tự được quyết định bởi ưu tiên toán tử và kết hợp. – EJP

1

Bởi vì một postincrement đổi các biến sau khi giá trị được lấy và + = đánh giá phía bên tay trái của nó trước khi đánh giá bên tay phải của nó,

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

trở thành

tmp0 = x 

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

x = tmp0 + x 
+0

Bạn có chắc chắn yo có nghĩa là phía bên tay trái được đánh giá TRƯỚC phía bên tay phải, bởi vì tôi nghĩ rằng tôi biết ngược lại? Việc ngắt mã là tốt, ngoại trừ câu lệnh cuối cùng x = tmp0 + x không cho kết quả là 63 cho x = 3. –

+0

Nếu không, nó sẽ là 66 thay vì 63. – Dan

2

Nhà điều hành postfix x++ nghĩa cái gì đó như "cho tôi giá trị của x bây giờ, nhưng tăng nó để tham khảo trong tương lai"

Vì vậy, bởi order of operations and evaluation,

x++ * x++ * x++

được diễn giải trước tiên là

3 * 4 * 5 (= 60)

mà sau đó được bổ sung vào gốc 3, năng suất 63.

Giá trị ban đầu được sử dụng vì nó là trên cùng một dòng, đã bạn viết một cái gì đó như:

int x = 3; 

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

x bây giờ sẽ là 66, thay vì 63, bởi vì x trong dòng thứ hai bây giờ là 6, thay vì ban đầu của nó 3.

1

unary operato rs đánh giá trái sang phải, vì vậy x++ đầu tiên nhận được giá trị x, thứ hai là (x+1), vv Và + = đánh giá theo giá trị của x lúc bắt đầu, vì thế việc bổ sung các x

5

Không có gì để làm với ưu tiên toán tử cho mỗi lệnh, chỉ là thứ tự đánh giá. Hai điều cần biết ở đây:

  1. x++ là thặng dư postfix, vì vậy giá trị của x được tăng sau nó được đánh giá
  2. * đánh giá phía bên phải rồi bên trái.

Xét điểm 2, biểu thức x++ * x++ * x++ có thể được viết lại cụ thể hơn là x++ * (x++ * (x++)).

Toàn bộ biểu thức có thể được viết như các thủ tục:

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

Cảm ơn bạn, việc ngắt mã sẽ giúp :) –

+0

1, nhưng với nitpick: Trên thực tế, ưu tiên toán tử có hiệu lực ở mọi nơi, nơi bạn có nhiều toán tử trong mệnh đề expression hoặc statement :) và toán tử postfix có ưu tiên cao hơn toán tử nhị phân, và đây là lý do tại sao 'x ++ * x ++' có thể được viết ** mà không có dấu ngoặc đơn **. Bạn sẽ phải viết '(x ++) * (x ++)'. Nếu không có toán tử ưu tiên và parens, chỉ từ phải sang trái sẽ diễn ra, và _could_ có nghĩa là 'x ++ * (x ++))', ví dụ có thể là lỗi cú pháp: không có toán hạng LHS cho * – quetzalcoatl

+0

Được rồi, đủ công bằng. Tôi chỉ đơn giản có nghĩa là câu trả lời sẽ có liên quan nhiều hơn đến hành vi của các toán tử postfix và prefix như trái ngược với quyền ưu tiên của toán tử như trong trường hợp biểu thức kết hợp nhiều toán tử ưu tiên khác nhau (ví dụ: 'x ++ * x ++ + x ++/x ++ ') –

2

Bởi vì hoạt động increment ++ được thêm vào sau khi biến x. Đó là một hoạt động tăng bài viết. Điều đó có nghĩa, x được tăng lên sau khi thao tác được xử lý.

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. 

Nếu bạn muốn biến của bạn tăng lên trước khi phẫu thuật được thực thi, bạn phải viết ++ x (pre hoạt động increment)