X == (x = y) uyğun olmayan səbəb (x = y) == x?

Aşağıdakı nümunəni nəzərdən keçirin:

 class Quirky { public static void main(String[] args) { int x = 1; int y = 3; System.out.println(x == (x = y)); // false x = 1; // reset System.out.println((x = y) == x); // true } } 

Java dilinin spesifikasiyası əvvəlcədən parantezlər ilə nəzərdə tutulmuş qaydada hesablanmalı olan sağ tərəfə ( x = y ) müqayisə üçün bir dəyişənin əvvəlki dəyərini yükləməyi əmələ gətirən bir elementdən ibarətdir.

Niyə ilk ifadə false , ikincisi isə true ? Mən (x = y) əvvəlcə qiymətləndirilməsini gözləyirdim, sonra özünü x ( 3 ) ilə müqayisə edəcəyini və true dönəcəyini düşündüm.


Bu sual, x ifadəsində olan subexpressionların qiymətləndirilməsi qaydasından fərqlənir ki, burada x mütləq bir "subexpress" deyildir. Müqayisə üçün müqayisə etmək lazımdır, "qiymətləndirmək" deyil. Sual Java üçün xarakterikdir və x == (x = y) ifadəsi, mürəkkəb müsahibə sualları üçün yaradılmış qeyri-praktik konstruksiyalardan fərqli olaraq real layihədən yaranıb. Bu müqayisə və dəyişdirmə üçün bir xəttin dəyişdirilməsi idi

 int oldX = x; x = y; return oldX == y; 

x86 CMPXCHG təlimatından daha sadə olan, Java-da daha qısa bir ifadəyə layiqdir.

149
12 дек. John McClane tərəfindən təyin olunan 12 dekabr. 2018-12-12 22:11 '18 saat 10:11 'də 2018-12-12 22:11
@ 17 cavab

parantezlərdə göstərilən qaydada ilk olaraq hesablanmalıdır

Xeyr Bu, parantezlərin hesablama və qiymətləndirmə qaydalarına (ümumi) təsir göstərdiyinə dair ümumi yanlış fikirdir. İstədiyiniz operandları iş üçün düzgün əməliyyatlarla birləşdirərək, yalnız sizin ifadələrinizin hissələrini müəyyən bir ağaca çevirirlər.

(Əgər siz onları istifadə etmirsinizsə, bu məlumatlar dilin sintaktik ağacının necə müəyyənləşdirildiyinin nəticəsidir olan operatorların "prioritet" və assosiasiyasından gəlir. Əslində, brackets istifadə edərkən işlədilir, lakin biz sadələşdiririk və demək ki, biz heç bir prioritet qaydalarına güvənməyəcəyik.)

Bu edildikdən sonra (yəni kodunuz proqramda təhlil edildikdə) bu işçilərin hələ qiymətləndirilməsinə ehtiyac var və bunun necə aparıldığına dair ayrı-ayrı qaydalar var: qeyd olunan qaydalar (Andrew bizə göstərdi) hər LHS əməliyyatlar ilk olaraq java olaraq sıralanır.

Xahiş edirik bütün dillərdə belə deyil; məsələn, C ++ da, qısa bir dövr operatoru kimi istifadə > və > və ya || Operandların qiymətləndirilməsi qaydası adətən müəyyənləşdirilmir və siz də ona etibar etməməlisiniz.

Müəllimlər, "bu ilk əlavə edir." Kimi yanlış ifadələr istifadə operator prioritet izah dayandırmaq lazımdır. x * y + z ifadəsi üçün, düzgün izah "operatorun prioriteti" x * yy arasında deyil, x * yz arasındakı əlavə meydana gəlməsinə gətirib çıxarır ", hər hansı bir" qaydada "qeyd etmədən.

62
13 дек. Cavab 13 dekabrda Orbitdə Lightness Yarışları tərəfindən verilir. 2018-12-13 14:08 '18 saat 02:08 'da 2018-12-13 14:08

== ikili bərabərlik operatorudur.

border=0

Görünür ki, sağ operatorun hər hansı bir hissəsi hesablanmadan əvvəl ikili operatorun sol işarəsi tamamilə hesablanır.

Java 11 spesifikasiyası> Qiymətləndirmə qaydası> Əvvəl sol operandın qiymətini qiymətləndirin

147
12 дек. Cavab Andrew Tobilko tərəfindən verilir 12 dekabr. 2018-12-12 23:24 '18 də 23:24 2018-12-12 23:24 'də

Louis Wasserman dediyi kimi ifadə soldan sağa dəyərləndirilir. Və java həqiqətən nə müəyyən edir ki, qayğı deyil, yalnız iş üçün dəyəri (qeyri-uçucu, son) yaratmaq üçün qayğı.

 //the example values x = 1; y = 3; 

Belə ki, System.out.println() 'nin ilk çıxışını hesablamaq üçün aşağıdakı işlər görülür:

 x == (x = y) 1 == (x = y) 1 == (x = 3) //assign 3 to x, returns 3 1 == 3 false 

ikinci hesablayın:

 (x = y) == x (x = 3) == x //assign 3 to x, returns 3 3 == x 3 == 3 true 

Birincisi xy dəyərlərindən asılı olmayaraq, ikinci dəyəri həmişə doğru olduğuna diqqət yetirin, çünki dəyərin tapşırığını təyin olunmuş dəyişənə müqayisə edərək, a = bb bu qaydada qiymətləndiriləcəkdir, həmişə eyni təyinatla eyni olacaq .

126
12 дек. Cavab Poohl 12 dekabr verilir. 2018-12-12 22:46 '18 saat 10:46 'da 2018-12-12 22:46

Bir dəyişənin əvvəlki dəyərini yükləməyi tələb edən Java dilinin dəqiqləşdirilməsində bir element olduğuna əmin deyiləm ...

Orada var. Növbəti dəfə, dəqiqləşdirmənin nə dediyi aydın deyilsə, onu oxuyun və sonra aydın olmadığını soruşun.

... sağ tərəfdə (x = y) parantezdə göstərilən qaydada ilk hesablanmalıdır.

Bu bəyanat səhvdir. Mötərizədə qiymətləndirmə qaydası nəzərdə tutulmur . Java'da, parantezlərdən asılı olmayaraq, hesablama qaydası soldan sağa doğru. Mötərizələr subexpressiyanın sərhədlərinin qiymətləndirmə qaydası deyil, harada olduğunu müəyyən edir.

Niyə ilk ifadə yanlış, ikincisi isə doğru sayılır?

Operator üçün qayda == : dəyərini almaq üçün sol tərəfi hesablayın, dəyəri almaq üçün sağ tərəfi hesablayın, dəyərləri müqayisə edin, müqayisədə ifadə dəyəridir.

Başqa sözlə, expr1 == expr2 dəyəri temp1 = expr1; temp2 = expr2; yazdığınız kimi həmişə temp1 = expr1; temp2 = expr2; temp1 = expr1; temp2 = expr2; temp1 = expr1; temp2 = expr2; və sonra temp1 == temp2 .

Operator üçün qayda = soldakı yerli dəyişəndən: dəyişənliyi almaq üçün sol tərəfin hesablanması, dəyəri almaq üçün sağ tərəfin hesablanması, tapşırığın yerinə yetirilməsi, nəticə təyin edilmiş dəyərdir.

Birlikdə qoyun:

 x == (x = y) 

Bir müqayisə operatorumuz var. Qiyməti almaq üçün sol tərəfi qiymətləndiririk - x nin cari dəyərini alırıq. Sağ tərəfi qiymətləndirin: bu tapşırıqdır, buna görə biz dəyişəni almaq üçün sol tərəfi qiymətləndiririk - dəyişən x - sağ tərəfi qiymətləndiririk - y nin cari dəyəri - x verin və nəticə təyin edilmiş dəyərdir. Sonra orijinal x dəyərini təyin edilmiş dəyərlə müqayisə edirik.

Siz (x = y) == x edə bilərsiniz. Yenə də unutmayın ki , sol tərəfi qiymətləndirmək üçün bütün qaydalar sağ tərəfin qiymətləndirilməsi üçün bütün qaydalara üstünlük verir .

Mən (x = y) əvvəlcə qiymətləndirilməsini gözləyirdim, sonra özünü x (3) ilə müqayisə edəcəyini və həqiqətə dönəcəyini düşündüm.

Sizin gözləntiniz Java qaydaları ilə bağlı bir sıra yanlış fikirlərə əsaslanır. Ümid edirəm indi doğru inanclar var və gələcəkdə də həqiqəti gözləyəcəksiniz.

Bu sual bir "Java ifadəsində subexpressions qiymətləndirilməsi qaydasından" fərqlidir

Bu bəyanat səhvdir. Bu sual tamamilə müvafiqdir.

x burada mütləq "subexpress" deyil.

Bu bəyanat da yanlışdır. Bu subexpression hər nümunədə iki dəfədir.

Müqayisə üçün müqayisə etmək lazımdır, "qiymətləndirmək" deyil.

Bunun nə olduğunu bilmirdim.

Göründüyü kimi, hələ də bir çox yalan inancınız var. Mənim məsləhətim, yalan inancınızın əsl inancları ilə əvəz olunmadığı qədər dəqiqliyi oxumaqdır.

Sual Java üçün xarakterikdir və x == (x = y) ifadəsi, ümumiyyətlə, mürəkkəb müsahibə üçün yaradılan qeyri-praktik konstruksiyalardan fərqli olaraq gerçək bir layihədən gəldi.

Sözün mənşəyi bu sual ilə əlaqəli deyil. Bu ifadələr üçün qaydalar dəqiqləşdirmədə aydın şəkildə təsvir olunur; oxuyun!

Bu müqayisə və dəyişdirmə üçün bir xəttin dəyişdirilməsi idi

Bu bir satırda əvəz etdiyinizə görə kod oxuyucusu, bir çox qarışıqlıq, mən bu pis bir seçim olduğunu söyləyərdim. Kodu daha qısa, anlamaq daha çətin bir zəfər deyil. Kodun daha sürətli olacağı ehtimalı yoxdur.

Yeri gəlmişkən, C # -də bir kitabxana metodu şəklində bir müqayisə üsulu və əvəz üsulu mövcuddur, bu da bir maşın təlimatı ilə müqayisə edilə bilər. Java tipli sistemdə təmsil edilə bilmədiyi üçün Java belə bir üsula malik olmadığına inanıram.

14
15 дек. Cavab Eric Lippert tərəfindən 15 dekabrda verilir. 2018-12-15 01:38 '18 'də 1:38' də 2018-12-15 01:38 'də

Bu, operatorların prioritetləri və operatorların qiymətləndirilməsi ilə bağlıdır.

Konsollar '()' daha yüksək prioritet və soldan sağa birləşmə var. Bu sualın yanında '==' bərabərliyi var və soldan sağa birləşmə var. '=' Vəzifəsi sonuncudur və sağdan sola birliyə malikdir.

Sistem, ifadəni qiymətləndirmək üçün yığını istifadə edir. Söz soldan sağa dəyərləndirilir.

İndi orijinal sualına gəlir:

 int x = 1; int y = 3; System.out.println(x == (x = y)); // false 

Birincisi, x (1) yığın üzərində itələmək olacaq. sonra daxili (x = y) qiymətləndiriləcək və x (3) dəyəri ilə yığın üzərinə basdırılacaq. İndi x (1) x (3) ilə müqayisə olunacaq, nəticədə yalançı olur.

 x = 1; // reset System.out.println((x = y) == x); // true 

Burada (x = y) qiymətləndiriləcək, indi x xü 3, x (3) isə yığın üzərinə basdırılacaq. İndi bərabərlikdən sonra dəyişdirilmiş dəyəri ilə x (3) yığının üstünə itələmək olacaq. İndi ifadə dəyərləndiriləcək və hər ikisi eyni olacaq, nəticə isə düzgündür.

12
13 дек. cavabına Amit 13 dekabr verilir . 2018-12-13 15:25 '18 saat 15:25 'da 2018-12-13 15:25

Bu eyni deyil. Sol tərəf həmişə sağdan əvvəl qiymətləndiriləcək və parantezlərdə icra əmri deyil, əmrlərin qruplaşdırılması.

Kimdən:

  x == (x = y) 

Siz əsasən eyni şeyi edirsiniz:

  x == x 

Sonra qiymətdən aldı. Və həmişə həqiqəti qaytaracaqdır.

9
13 дек. Cavab 13 dekabrda verilir. 2018-12-13 23:17 '18 saat 11:17 'da 2018-12-13 23:17

İlk testdə, 1 == 3 olub.

İkinci testdə, çekiniz 3 == 3 olur.

(x = y) bir dəyər təyin edir və bu dəyər yoxlanılır. İlk nümunədə x = 1 birinci təyin edilir, sonra x 3 təyin edilir. 1 == 3?

Sonuncu halda, x 3 təyin edilir və açıq-aydın görünür ki, hələ 3. 3 == 3?

7
13 дек. 13 dekabrda Michael Puckett II tərəfindən verilmiş cavab . 2018-12-13 07:03 '18 'də 7:03' də 2018-12-13 07:03

Başqa, bəlkə də daha sadə bir nümunə baxın:

 int x = 1; System.out.println(x == ++x); // false x = 1; // reset System.out.println(++x == x); // true 

Burada, müqayisə edilməzdən əvvəl ++x ilkin artım operatoru tətbiq olunmalıdır - nümunənizdə olduğu kimi (x = y) müqayisədən əvvəl hesablanmalıdır.

Ancaq ifadənin qiymətləndirilməsi hələ də soldan sağa doğru olur , belə ki, ilk müqayisə həqiqətən 1 == 2 , ikincisi isə 2 == 2 .
Eyni şey sizin nümunənizdə olur.

7
14 дек. Luis G. tərəfindən verilmiş cavabı 14 dekabr. 2018-12-14 12:00 '18 saat 12:00 'də 2018-12-14' da saat 12.00 'də

İfadələr soldan sağa dəyərləndirilir. Bu vəziyyətdə:

 int x = 1; int y = 3; 

 x == (x = y)) // false x == t - left x = 1 - let t = (x = y) => x = 3 - x == (x = y) x == t 1 == 3 //false 

 (x = y) == x); // true t == x - left (x = y) => x = 3 t = 3 - (x = y) == x - t == x - 3 == 3 //true 
5
14 дек. Simonare tərəfindən verilmiş cavab 14 dekabr . 2018-12-14 23:17 '18 saat 11:17 'də 2018-12-14 23:17' də

Əslində, ilk x x dəyərinə 1 malikdir, beləliklə Java 1 == yeni dəyişən x ilə müqayisə edilir, bu da eyni olmayacaq

İkincisi, x = y dediniz, yəni x dəyəri dəyişdi və buna görə də yenidən çağırdığınız zaman eyni olur, buna görə də doğru olur və x == x

4
14 дек. Əhməd Bedirxan tərəfindən verilmiş cavab 14 dekabr. 2018-12-14 03:35 '18, 3:35 'də 2018-12-14 03:35' a qədər

Kodunuz üçün if ifadəsi kimi c ++ istifadə etdim və onlar bərabərdir:

 #include <iostream> #include "conio.h" using namespace std; int main() { int x = 1; int y = 3; if(x == (x = y)  (x = y) == x) cout<<"fine"; else cout<<"wrong"; getch(); return 0; } 
0
13 дек. Cavab Moataz Ahmed Samy tərəfindən 13 dekabrda verilir. 2018-12-13 16:46 '18 ' də saat 04:46' da 2018-12-13 16:46 'də

Big Bru,

 class Quirky { public static void main(String[] args) { int x = 1; int y = 3; System.out.println(x == (x = y)); // (1 == (x=3)) x = 1; // reset System.out.println((x = y) == x); // ((x=3) == 3) } 

}

Bütün ev uşaqlarının dediyi kimi, ikili bərabərlik operatorunun sol tərəfi "==" həmişə ilk hesablanır! İkinci nümunədə, x 3 təyin edildikdən sonra gerçək olan cari özüylə müqayisə edilir! İlk nümunədə, x qiymətləndirilir və sonra sağ tərəfdən 3-ə təyin olunur.

0
15 дек. Cavab Alan Judi tərəfindən verilir. 2018-12-15 14:51 '18 at 2:51 pm 2018-12-15 14:51

== müqayisə üçün bərabərlik operatorudur və soldan sağa doğru işləyir.

 x == (x = y); 

burada xin köhnə təyin dəyəri x təyin olunmuş yeni dəyərlə müqayisə edilir (1 == 3) // false

 (x = y) == x; 

Burada yeni təyin edilmiş x x'sinin müqayisə edilməzdən əvvəl ona təyin edilmiş yeni x dəyərinə x ilə müqayisə olunduğunu nəzərə alaraq, (3 == 3) // true

İndi düşün

  System.out.println((8 + (5 * 6)) * 9); System.out.println(8 + (5 * 6) * 9); System.out.println((8 + 5) * 6 * 9); System.out.println((8 + (5) * 6) * 9); System.out.println(8 + 5 * 6 * 9); 

Çıxış:

342

278

702

342

278

Beləliklə, parantezlər müqayisə ifadələrində deyil, arifmetik ifadələrdə mühüm rol oynayır.

0
22 дек. Cavab Nisrin Dhoondia 22 dekabrda verilir . 2018-12-22 21:00 '18 saat 21:00 'də 2018-12-22 21:00' də

Bir Java derleyici və ya Java derleyicisinin doğruluğunu doğrulamak üçün test proqramları yazmaq istəsəniz soruşduğunuz sual çox yaxşı bir sualtır. Java'da bu iki ifadə sizin gördüklərinizin nəticələrini verməlidir. Məsələn, C ++-da, bunlara ehtiyac yoxdur - belə ki, əgər kimsə C ++ kompilyatorunun bir hissəsini onların Java kompilyatorunda təkrar istifadə etsə, teorik olaraq kompilyatorun lazım olduğu kimi davranmadığını tapa bilərsiniz.

Bir proqram inkişaf etdiricisi oxunaqlı, anlaşılan və asan saxlanılan kod yazarkən kodunuzun hər iki versiyası da dəhşətli olacaq. Kodun nə olduğunu anlamaq üçün tam olaraq Java dilinin necə müəyyənləşdirildiyini bilmək lazımdır. Java və C ++ kodunu yazan kimsə kodda titrəydi. Bir kod kodunun nə üçün etdiyini soruşmasanız, bu koddan qaçın. (Güman edirəm və ümid edirəm ki, düzgün cavab verən uşaqlar nəyə görə bu sualın özü də özlərini çəkəcəklər).

-1
15 дек. cavab gnasher729 15 dekabr tərəfindən verilir . 2018-12-15 14:29 '18 saat 02:29 'da 2018-12-15 14:29

Yuxarı müqayisə edərkən sola - asanlıqla yx (solda) verildikdən sonra tapşırıq verin, sonra 3 == 3 müqayisə edin. Birinci nümunədə x = 1-i yeni təyinat x = 3 ilə müqayisə edirsiniz. Görünür oxucu operatorlarının mövcud vəziyyəti həmişə soldan sağa x

-1
18 дек. Michał Ziobro tərəfindən verilmiş cavab 18 dekabr. 2018-12-18 21:57 '18 saat 21:57 2018-12-18 21:57
 Here most important thing to note is, expression inside (...) gets priority for execution and order of operation. System.out.println(x == (x = y)); // false (x == (x = y)) (1 == (1 = 3)) (1 == (3)) **False** x = 1; // reset System.out.println((x = y) == x); // true ((x = y) == x) ((1 = 3) == x) ((3) == x) ((3) == 3) **True** 
-1
14 дек. Cavab Kunal Shira tərəfindən 14 dekabrda verilir. 2018-12-14 19:55 '18 saat 07:55 'da 2018-12-14 19:55

variable == true olmadığını kontrol etmek üçün ilk defa çekinizi kontrol edərkən çox sadədir, lakin ikinci dəfə valid expression == variable və ya valid expression == variable valid expression == variable yoxlamaq üçün yoxlayın.

Qeyd edək ki, əgər x != null || 0 || false x != null || 0 || false x != null || 0 || false x != null || 0 || false x != null || 0 || false x != null || 0 || false x != null || 0 || false x != null || 0 || false x != null || 0 || false olduqda o, doğru hesab ediləcək.

x == (x = y) eyni deyil (x = y) == x çünki:

Birincisi sadəcə if x == true soruşur
İkincisi, if function.wasExecuted == trueif function.canExecute == true (əgər x x-yə təyin olursa) qaytarırsa (əgər x xətti varsa və ya başqa bir səbəbdən y)
Bu tip ifadənin başqa bir nümunəsi if (alert("hi") == true) alert () funksiyası yerinə yetirilə bilərsə, bu doğru olur.

Məsələn: JSFiddle (bəli, Java üçün soruşduğunuzu bilirəm, amma bu məntiq JavaScript-də keçirilir)

-3
17 дек. Cavab Techtiger255 Kod Müddəti verildi 17 dekabr. 2018-12-17 08:13 '18 saat 20:13 'də 2018-12-17 08:13