Koşullu ifadede bitsel bir işleç ne zaman kullanılabilir?


15

İlk olarak, bir arka plan: Ben bir BT eğitim-öğretmeni ve java'nın boolean operatörlerini 10. sınıfımla tanıştırmaya çalışıyorum. Öğretmen akıl hocam, hazırladığım ve sadece tek bir & "aynı şeyi yapıyorlar" çünkü operatörleri belirtmek için.

& Ve && arasındaki farkın farkındayım.
&, "bit-twiddling" gerçekleştirmek için tamsayılar arasında kullanılmak üzere tasarlanmış bir bitsel operatördür.
&&, boole değerleri arasında kullanılmak üzere tasarlanmış koşullu bir operatördür.

Bu operatörlerin her zaman "aynı şeyi yapmadığını" kanıtlamak için, boole değerleri arasında bitsel kullanmanın bir hataya yol açacağı bir örnek bulmak için yola çıktım. Bu örneği buldum

boolean bitwise;
boolean conditional;
int i=10, j=12;
bitwise = (i<j) | ((i=3) > 5); // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10; 
conditional = (i<j) || (i=3) > 5 ;  // value of i after oper: 10
System.out.println(conditional+ " "+ i);
i=10; 
bitwise = (i>j) & (i=3) > 5;   // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10; 
conditional = (i>j) && (i=3) > 5;  // value of i after oper: 10
System.out.println(conditional+ " "+ i);

Bu örnek, bir değerin ifadenin ikinci yarısına kadar değiştirilmesi gerektiğinde, koşulların kısa devre olarak davrandığını ( yarım, ilk yarım yanlışsa && durumunda doğru ise ||).

Bu örnekle ilgili bir sorunum var. Neden bir değeri karşılaştırırken yaptığınız bir değeri değiştirmek istersiniz? Kodlamanın sağlam bir yolu gibi görünmüyor. Üretim kodumda her zaman tek bir satırda birden fazla işlem yapmaktan kaçındım. Kodunun sürdürülebilirliği konusunda vicdanı olmayan "kodlayan bir kovboy" gibi görünüyor. Bazı etki alanlarında kodun olabildiğince kompakt olması gerektiğini biliyorum, ama kesinlikle bu genel olarak kötü bir uygulama mı?

&& ve || kullanımını teşvik etme seçimimi açıklayabilirim fazla & | çünkü bu yazılım mühendisliğinde kabul edilen bir kodlama kuralıdır .

Ama birileri bana koşullu bir ifadede bitsel bir operatör kullanma örneği olarak daha iyi, hatta gerçek bir dünya verebilir mi?

Yanıtlar:


16

bir maskeleme işlemi yaparken uygundur

eğer ((a & b)> 0) {...}

burada a ve b tamsayıdır

|| ve | ve && ve & değiştirilemez

| ve & hiçbir zaman koşullu bir ifadede asla kendiliğinden görünmez (eklediğiniz bağlantının noktası, bu tür şeylerin çoğu zaman hata olmasıdır)

EDIT: Mentor ile tartışmayın; kazansan bile kaybedersin. Bunun yerine, aynı derste mantıksal işleçleri ve bitsel işleçleri karıştırarak öğrencileri karıştırmak istemediğinizi açıklayın. Eğer i = 3 ve j = 2 ise i & j = 2 ise, i && j bir hata olduğunu açıklayabilirsiniz. Bununla birlikte, daha basit açıklama, boole (mantıksal) operatörleri öğrettiğinizdir, bu nedenle özel durum bitsel eşdeğerlerini atmak, dersin ana noktasından bir oyalamadır. Mentorun "yanlış" yapılmasına ve karşı örnekler üretmeye gerek yoktur. Dersin odak noktası, bitsel operatörler değil , boole operatörleridir.

Bir sonuç olarak, bitsel operatörleri öğretmeye başladığınızda, + ve - ile & ve |


Yukarıdaki kod yanlış olmasa da, kafa karıştırıcı olabilir, ancak kodun bir hata içermediği anlamına gelir mi? Bitwise işleçlerini bu şekilde kullanmanın çok okunabilir olmadığını kabul ediyorum, bir kod incelemesinde gördüm, ancak yasal Java (ve C # de, System.out.println yok sayılıyor) hoşuna gitmiyor.
Steve

@Steven A. Lowe cevapladığınız için teşekkür ederiz. Dedin "|| ve | ve && ve & birbirinin yerine geçemez" ama bitwise = !(true & true == false);ve condition = !(true && true == false);her ikisi de birbirlerinin yerine Dolayısıyla bu durumda, true değerlendirecek? Sözdizimsel olarak belki de kod hala derlendiğinden. 2. paragrafta bahsettiğim gibi, bunların semantik olarak farklı şeyler için kullanılmasına katılıyorum. ve & "neredeyse hiçbir zaman kendi şartlarında görünmezler". Bu "neredeyse hiç" davalarını arıyorum ve meşru olarak var olup olmadıklarını merak ediyorum.
Deerasha

@Deerasha: || ve && yalnızca booleanlarda çalışır . & ve | tamsayılar ve boolean'lar üzerinde çalışın - booleanları manipüle etmek için bitsel operatörler ( birden çok bit üzerinde çalışacak şekilde) kullanmanın çok az anlamı vardır ve bunu terk etmek kafa karıştırıcı kodlara ve beklenmedik davranışlara yol açabilir (yani yanlışlıkla bir tamsayı kullanırsanız boolean, bitsel operatörler şikayet etmeyecek)
Steven A. Lowe

Evet @Steve Haigh, derleyici bunu reddetmiyor, ancak bağlantılı olduğum yayınlanmış kodlama standardından yola çıkarak bunları kullanmanın doğru yolu değil. Bir kodlama standardına uymadığı için onu rahatça reddedebilir miyim, yoksa java bunun yanlış bir kullanım olduğunu gösterebilir mi?
Deerasha

2
@Steven A. Lowe: i = 3 ve j = 2 ise, i & j = 2 ise, i && j bir hatadır Bu mükemmel! Çok basit ve önemli. 10. sınıf seviyesinde, Boole tipine hâlâ alışkın oldukları ve operatörlerin neye başvuracakları da bu muhtemelen olası bir hatadır. Çok teşekkür ederim! Mentörümle tartışmamaya da büyük tavsiye.
Deerasha

12

Bitsel olmayan operatörler &&ve ||kısa devre operatörleridir. Başka bir deyişle, &&eğer LHS yanlışsa, RHS asla değerlendirilmez; ile ||LHS doğruysa, o zaman RHS değerlendirilecektir asla. Öte yandan, bitsel operatörler &ve |kısa devre değildir ve her zaman hem LHS'yi hem de RHS'yi değerlendirecektir. Aksi takdirde, bir ififadede eşdeğerdirler .

Kısa devre dışı operatörleri kullanırken değeri görebildiğim tek zaman, RHS'nin her durumda olmasını istediğiniz bir tür arzulanan yan etkisi olup olmadığıdır. Bunu isteyeceğiniz belirli bir örnek düşünemiyorum ve bunun iyi bir uygulama olduğuna inanmıyorum, ama fark bu.


1
+1. Tam olarak doğru, booleans bitsel ve mantıksal işleçleri karşılaştırırken her zaman aynı sonucu döndürür, ancak (en azından Java ve C # 'da) yalnızca mantıksal işleçlerin kısa devresi.
Steve

Cevap verdiğiniz için teşekkür ederim. 1. paragrafınız , koşullu kısa devre gibi davranırken bitselin istekli bir operatör olduğunu belirterek 4. paragrafımda almaya çalıştığım şeydi . 2. paragrafınız 5. paragrafımda tanımladığım kaygıdır. Bu yüzden farkın farkındayım ama ne siz ne de düşünebileceğim belirli bir örnek arıyorum.
Deerasha

7

Genel felsefi cevap, boole operatörleri için bitsel operatörlerin kullanılmasının atipik olması ve kodun okunmasını zorlaştırmasıdır. Uygulamada (üretimde olan kod için), daha okunabilir kodun bakımı daha kolaydır ve bu nedenle daha arzu edilir.

Kısa devre operatörleri ihtiyacının gerçek dünyada kullanımı için aşağıdaki gibi durumlara bakın:

if (args.length > 0 && args[0] == 'test') ....

if (b != NULL && b.some_function()) ...

if (b == NULL || b.some_function()) ...

Bu tür işlemler gerçek dünya kodunda sıkça görülür.


Tfa. 15 yaşındaklarıma, 1'in &2'den “daha ​​zor” olduğunu nasıl anlarım ? İki operatörün Boolean işlenenleri için aynı şekilde çalışmadığı bir örneğim yok. Daha okunaklı ve bakımı daha kolay kod konusunda hemfikirim. Onları güzel kod yazmaya teşvik etmek istiyorum. Ama alet çantamda bir kanıta sahip olmak “çünkü öyle dedim” den daha ikna edici olurdu. Bu bağlantıda bir standart olarak ifade ettim ve aradığım örneği almazsam yalnız başına güvenmek zorunda kalabilirim. Sorduğum gibi @Steve Haigh: java bunu uygunsuz bir kullanım olarak mı göstermeli?
Deerasha

@Deraerasha Mentorunuzla daha fazla tartışmayı düşünüyordum. Sınıf için onlara mantıksal koşullar için bitsel işleçleri kullanabileceğinizi söylemeye bile çalışmayın.
Kathy Van Stone

4

Bitmask numaralandırmalarını karşılaştırırsanız bitsel işleçleri kullanırsınız. Örneğin, bir eyalet numaralandırması ve bu eyaletlerden birden fazlasında olabilecek bir nesneniz var. Bu durumda, bitsel olarak veya nesnenize birden fazla durum atamanız gerekir.

örneğin state = CONNECTED | IN_PROGRESSnerede CONNECTED could be 0x00000001veIN_PROGRESS 0x00000010

Daha fazla bilgi için bayrak numaralandırma belgelerine bakın.


Sayende daha önce bilmediğim bitsel operatörlerin bir uygulamasını öğrendim! Ancak bu örnekte, yalnızca bitsel operatör uygulanır. Koşullu yerine bitsel kullanarak derleme, ancak yanlış bir çıkış yol açacaktır iyi yazılmış bir kod parçası arıyorum. Yani, böyle bir kod pasajı varsa.
Deerasha

Bu arama Java inanıyorum gibi sanmıyorum | veya & operatörleri bitsel olamaz ve sadece mantıksal gerçekleştiren veya yapamayan değerler | veya &. Java durumda olup olmadığını hatırlayamıyorum, ancak C # MSDN'de olduğundan emin olun: "İkili | işleçleri ayrılmaz türleri ve bool için önceden tanımlanmıştır. İntegral türleri için, | bitlerinin VEYA işlenenlerinin bitselini hesaplar. bool işlenenleri, | işlenenlerinin mantıksal
OR'sini

Biraz daha araştırma yaptıktan sonra, | ve || Java'daki boolean işlenenler için & & && kısa devre davranışıdır, bu nedenle tanımladığınız senaryo gerçekten mümkün değildir.
pwny

0

daha basit bir yanlışlık örneği:

int condA=1, condB=2;

if (condA!=0 && condB!=0) {
    // correct!
}
if ((condA & condB)!=0) {
    // never executed
}

burada iki koşulunuz var, ikisi de sıfır değil; fakat bitsel &sıfır ile sonuçlanır.


@Javier: Yanıtladığınız için teşekkür ederim, ama biraz kafam karıştı. Java'da çalışıyorum ve bu kod derlemiyor. (condA && condB)hatalar, && 2 intsaniye boyunca çalışmadığından , yalnızca 2 boolean. (condA & condB)doğru olsa da, bir int java olarak değerlendirir ve java olarak da söyleyemeyiz if(int). Ne aradığımı ilk anlayan sensin - tam olarak bu yanlışlık örneği .
Deerasha

Uzun zamandır Java kullanmadım ... denemek (Boolean(condA) && Boolean(condB)) (Bence Boolean(x)olduğunu true, doğru sıfırdan farklı tamsayılar için?)
Javier

@Javier: int'ten boole'ye dökülemiyor.
Deerasha

Ne hakkında ((condA!=0) && (condB!=0))?
Javier

@Javier yay derler, ancak "yanlışlık" artık gösterilmez if (((condA!=0) && (condB!=0))) { System.out.println("correct"); } if (((condA!=0) & (condB!=0))) { System.out.println("never executed?"); }her iki yazdırma deyimlerini yürütür.
Deerasha
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.