(X ^ 0x1)! = 0 ne anlama geliyor?


183

Aşağıdaki kod pasajıyla karşılaştım

if( 0 != ( x ^ 0x1 ) )
     encode( x, m );

Ne anlama x ^ 0x1geliyor? Bu standart bir teknik mi?


97
Kod gizleme oldukça standarttır.
raina77ow

47
Bu, "normal" bir denklem ile aynı yaklaşımla çözülebilir: 0 != (x ^ 1)→ veya her iki tarafı da 1 ile → (0 ^ 1) != (x ^ 1 ^ 1)→ basitleştir →1 != x
Score_Un

4
Nasıl if (1 != x)yazmanın zor olduğunu anlamıyorum .
Adriano Varoli Piazza

12
Çeşitli yorum yapılmamış, ilk @Spook tarafından açıkça işaret typeait xverilmez - dolayısıyla bu bu C bir tam sayıdır bilmiyorum ++ sorunu etiketledi. Elbette, bu C veya xbir tamsayı ise, cevap kolaydır, ancak bu verilmez ve aşırı yükleme olasılığı operator ^vardır.
chux - Monica'yı

11
Nasıl bu kadar çok oy alır görmüyorum ...
laike9m

Yanıtlar:


277

XOR işlemi ( x ^ 0x1) bit 0'ı tersine çevirir. Dolayısıyla ifade etkili bir şekilde şu anlama gelir: x'in 0 biti 0 veya başka bir x biti 1 ise, ifade doğrudur.

Tersine, x == 1 ise ifade yanlıştır.

Yani test aynı:

if (x != 1)

ve bu nedenle (tartışmalı olarak) gereksiz yere gizlenmiştir.


39
Hey, bağlamý bilmiyorsun. X bir tür bit bayrağıysa, şimdi olduğu gibi yazmak IMO'dur! = İşlecini kullanmaktan daha açıktır.
Spook

40
@Spook: sadece tek bir bit bayrağını test etmekle kalmıyor, x'in tüm genişliğini de test ediyor. Sadece tek bir biti test etmek istiyorsanız, bit şeklinde AND kullanmak gibi daha net deyimler vardır.
Paul R

115
Gereksiz yere gizlenmiş mi? Kodu gizlemek bizim işimiz olduğunu bilmiyor musun. Herhangi birinin anlayabileceği basit bir kod yazsaydık, neden, dünyadaki konumlarımızın dini kutsallığı nereye giderdi? Birden herkes gibi ortak çalışanlar olurduk. Gizleme doğası gereği gereklidir.
Thom

31
Aslında Spook haklı. Test (x! = 1) eşdeğer değildir. Kod C ++ olabilir (ve C ++, ^ her şeyi yapan bir operatör olabilir). Yani bağlamı bilmiyorsunuz, @Spook haklı.
xryl669

82
@TheThom уєт уσυ ωяιтє ιи ¢ ℓєαя тєχт
bobobobo

78
  • ^bitsel XOR işlemi
  • 0x1olan 1altıgen gösterimde
  • x ^ 0x1son bitini tersine çevirir x(bu size açık değilse yukarıdaki bağlantıdaki XOR doğruluk tablosuna bakın).

Yani, koşul (0 != ( x ^ 0x1 ))true olacaktır x1'den büyük olduğu veya son bit ise xbir değer olarak 0. Hangi sadece yaprakları x == 1 olduğundaki durum yanlış olacaktır. Yani eşdeğer

if (x != 1)

PS Cehennem böyle basit bir koşulu uygulamak için bir yol ekleyebilirim. Bunu yapma. Ve karmaşık kod yazmanız gerekiyorsa, bir yorum bırakın . Sana yalvarıyorum.


7
Öyle değil x==0; 4 ^ 0x1doğru, ama 4==0açıkçası yanlıştır.
Fred Foo

4
"koşul eşit görünüyor if (x == 0)", eşit değil x != 1mi?
Andrew-Dufresne

6
Eşdeğerlik x, integral bir tip olduğunu varsayar . Eğer bir floatya da ise double, o zaman ifadenin doğru olacağına inanıyorum 1.0 <= x < 2.0. Ve eğer xbir kullanıcı tanımlı türü ise, ifade doğru geri dönebilirler xYugo, kanguru, ünlü bestecinin doğum günü veya herhangi bir sayıda olan hisseleri Çin'de çayın cari dolar cinsinden fiyat ile en az üç rakam.
supercat

4
@supercat hiçbir bulunmamaktadır operator^için float/ ' double.
kabarık

1
@supercat: Kayan noktadan tam sayıya bir dönüşüm çağrıldığında, dönüşüm örtüktür (döküm sözdizimi gerektirmez). Ancak bitsel operatörler tarafından hiçbir dönüşüm tetiklenmez, sadece kayan nokta türleri için başarısız olurlar.
Ben Voigt

49

Bu basitleştirilmiş bir açıklama gibi görünebilir, ancak birisi yavaşça geçmek istiyorsa, aşağıdadır:

^c, c ++ ve c # ' da bitsel bir XOR operatörüdür.

Bitsel bir XOR, eşit uzunlukta iki bit paterni alır ve karşılık gelen her bir bit çifti üzerinde mantıksal özel OR işlemi gerçekleştirir.

Özel OR her iki giriş de farklı olduğunda doğru çıktı veren mantıksal bir işlemdir (biri doğrudur, diğeri yanlıştır).

Doğruluk tablosu içinde bir yada b :

a           b        a xor b
----------------------------
1           1           0
1           0           1
0           1           1
0           0           0

Şimdi 0 == ( x ^ 0x1 )ifadeyi ikili düzeyde gösterelim:

             what? xxxxxxxx (8 bits)
               xor 00000001 (hex 0x1 or 0x01, decimal 1)    
             gives 00000000
---------------------------
the only answer is 00000001

yani:

   0 == ( x ^ 0x1 )    =>    x == 1
   0 != ( x ^ 0x1 )    =>    x != 1

34

Özel OR (XOR) operatörüdür. Nasıl çalıştığını anlamak için bu basit kodu çalıştırabilirsiniz

    std::cout << "0x0 ^ 0x0 = " << ( 0x0 ^ 0x0 ) << std::endl;
    std::cout << "0x0 ^ 0x1 = " << ( 0x0 ^ 0x1 ) << std::endl;
    std::cout << "0x1 ^ 0x0 = " << ( 0x1 ^ 0x0 ) << std::endl;
    std::cout << "0x1 ^ 0x1 = " << ( 0x1 ^ 0x1 ) << std::endl;

Çıktı

0x0 ^ 0x0 = 0
0x0 ^ 0x1 = 1
0x1 ^ 0x0 = 1
0x1 ^ 0x1 = 0

Yani bu ifade

0 != ( x ^ 0x1 )

yalnızca x! = 0x1 olduğunda eşit olacaktır.

X'in kendisini değiştirmez. Yalnızca x'in 0 veya 1'e eşit olup olmadığını kontrol eder. Bu rxpression şu şekilde değiştirilebilir:

if ( x != 0x1 )

19

Bu kontroller xaslında değil 0x1... xoring xile 0x1eğer 0 sonuçlanacaktır sadece xolduğunu 0x1... Bu çoğunlukla birleştirici dili kullanılan eski hiledir


Bu daha hızlı mı != 1?
Fiddling Bits

2
Yanlış hatırlamıyorsam manuel montaj optimizasyonlar (x86) yaparken eski zamanlarda xoryaklaşım daha az makine kodu içeren ve daha hızlı karşılık gelen atama daha idam edildi 0... Ancak bu soru, bir içerdiği xorbunu düşünebilir böylece VE bir karşılaştırma !=olabilir Daha hızlı. Ancak, derleyici oluşturulan derleme görmek gerekir emin değilim.
Ferenc Deak

10
@BitFiddlingCodeMonkey: Hayır. XOR bazı yerel düzey eşitlik testinden daha hızlı olsaydı, derleyiciniz eşitliği test etmek için XOR'lar yayardı. Bu nedenle, XOR'lar derleyicileri optimize etme konusunda eşitlik testlerinden asla daha hızlı değildir. Hızlı kod yazmanın 101. kuralı "derleyiciye yardım etme. Sonunda sadece pratikte daha yavaş okunamayan kodlar hazırlayacaksın."
Matt

@Fritzone IIRC'de, XOR numaralarının kayıtların kaydedilmesiyle ilgisi vardı, kayıt yükünü b / c kaydederek, bazı durumlarda doğrudan OP'ye kodlanabilir ve durum bayrakları ile bazı ince farklılıklar vardı (ancak montajımın çoğu 68k ve DSP).
mpdonadio

1
@MPD: Normalde bir kaydı silmekle ilgilidir (en az 386+). xor eax, eax eax'ı iki baytta sıfıra ayarlar, ancak mov eax, 0 üç veya altı bayt alır (kodlamaya bağlı olarak) ve kod çözme işlemi xor formundan biraz daha uzun sürer .
Matt

18

^Operatör xor bit düzeyinde olduğunu. Ve onaltılık sabit olarak yazılmış 0x1sayıdır 1.

Yani, x ^ 0x1aynı x, ancak en az anlamlı bit ters çevrilmiş yeni bir değer olarak değerlendirir .

Kod, x'i 1 ile çok kıvrımlı ve belirsiz bir şekilde karşılaştırmaktan başka bir şey yapmaz.


11

Xor (özel veya) operatörü en çok bir veya daha fazla biti ters çevirmek için kullanılır. İşlem, tam olarak bitlerden birinin biri olup olmadığını sormaktır, bu aşağıdaki doğruluk tablosuna yol açar (A ve B girişlerdir, Y çıktıdır):

A    B    Y
0    0    0
0    1    1
1    0    1
1    1    0

Şimdi bu kodun amacı sadece son bitin 1 olup olmadığını ve diğerlerinin 0 olup olmadığını kontrol etmek gibi görünüyor, bu eşittir if ( x != 1 ). Bu belirsiz yöntemin nedeni, önceki bit manipülasyon tekniklerinin kullanılmış olması ve belki de programın başka yerlerinde kullanılması olabilir.


8

^bitler halinde xor operatorde c. Sizin durumunuzda x 1 ile xor'ed edilir. Örneğin x, 10 değeri vardır, 10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11dbu durumda koşul doğru olur.


Cevabında yazım hatası. 10 != 1010
Fiddling Bits

@BitFiddlingCodeMonkey: Yorumunuzdaki yazım hatası:10 (decimal) == 1010 (binary)
Paul R

6
@PaulR Oraya bir şey koymazsanız kimin ondalık ve ikilinin ne olduğunu bilmesi gerekir b?
Fiddling Bits

0b1010 bir şeyler yapmanın Pitonik yolu olmaz mıydı?
TankorSmash

8

Bitsel test kasıtlı bir gizleme gibi görünmektedir, ancak temel alınan veriler bir IBM ana bilgisayar sisteminden gelen kurumsal verilerse, kodun orijinal belgeleri yansıtmak için yazılmış olması olabilir. IBM veri formatları 1960'lara geri döner ve depolamayı kurtarmak için bayrakları bir sözcük içinde tek bit olarak sık sık kodlar. Biçimler değiştirildikçe, geriye dönük uyumluluğu korumak için mevcut kayıtların sonuna bayrak baytları eklenmiştir. Örneğin, bir SMF kaydının belgeleri, verilerin bir giriş dosyası olduğuna karar vermek için üç farklı sözcük içindeki üç ayrı biti tek bir kayıtta test etmek için montaj dili kodunu gösterebilir. TCP / IP dahili hakkında çok daha az şey biliyorum, ama orada bit bayrakları da bulabilirsiniz.


7

^ İşleci bitsel-xor'dur (bkz. &, |). Bit çifti için sonuç,

0 ^ 0 == 0
0 ^ 1 == 1
1 ^ 0 == 1
1 ^ 1 == 0

Yani ifade,

( x ^ 0x1 )

x'in 0 bitini tersine çevirir / çevirir (diğer bitleri değiştirmeden).

X'in 0x0 ve 0x1 dışında değerlere sahip olup olmadığını düşünün. X tek bir bit alanı olduğunda, sadece 0x0 ve 0x1 değerlerine sahip olabilir, ancak x bir int (char / short / long / etc) olduğunda, bit0 dışındaki bitler ifadenin sonucunu etkileyebilir.

Verilen ifade, bit0 yanındaki bitlerin sonucu etkilemesine izin verir,

if ( 0 != ( x ^ 0x1 ) )

Bu (daha basit) ifade ile eşdeğer doğrulukta olan,

if ( x ^ 0x1 )

Bu ifadenin yalnızca bit0'ı inceleyeceğini,

if( 0x1 & ( x ^ 0x1 ) )

Dolayısıyla, ifade edilen ifade gerçekten iki ifade kontrolünü birleştiriyor,

if( ( x & ~0x1 )  //look at all bits besides bit0
||  ( x ^ 0x1 ) ) //combine with the xor expression for bit0

Yazar sadece bit0'i kontrol etmek istiyor muydu ve bu ifadeyi mi kullanmak istiyordu,

if( 0x1 & ( x ^ 0x1 ) )

Yoksa yazar bit1-bitN ve bit0'in xor değerlerini gelmeye mi niyetli?


7

Yeni bir cevap ekliyorum çünkü kimse cevabı nasıl sezgisel olarak alacağını açıklamıyordu.

Ters +DİR -.
Ters ^DİR ^.

Nasıl çözmek mi 0 != x - 1için x? Her + 1iki taraf için de: 0 + 1 != x - 1 + 11 != x.
Nasıl çözmek mi 0 != x ^ 1için x? Her ^ 1iki taraf için de: 0 ^ 1 != x ^ 1 ^ 11 != x.


6

Başka bitler veya bit alanı değerleri olduğunu tahmin ediyorum xve bu sadece düşük dereceli bitin ayarlandığını test etmek için tasarlanmıştır. Bağlamda, bunun varsayılan olduğunu tahmin ediyorum ve bu nedenle bu ve bununla ilgili bazı kodlama m(muhtemelen kodlamak daha pahalı) atlanabilir, çünkü her ikisi de bir kurucuda veya benzerlerinde başlatılan varsayılan değer olmalıdır.

Bir şekilde kod çözücü, bu değerlerin eksik olduğunu çıkarabilmelidir. Bir yapının sonundalarsa, lengthher zaman mevcut olan bir değer aracılığıyla iletilebilirler .


4

XOR, C # flag enum'da yararlıdır. Enum değerinden tek bayrağı kaldırmak için x veya işlecini kullanmak gerekir ( buraya bakın )

Misal:

[Flags]
enum FlagTest { None 0x0, Test1 0x1, Test2 0x2, Test3 0x4}

FlagTest test = FlagTest.Test2 | FlagTest.Test3;
Console.WriteLine(test); //Out: FlagTest.Test2 | FlagTest.Test3
test = test ^ FlagTest.Test2;
Console.WriteLine(test); //Out: FlagTest.Test3

AMA soru C ++ hakkında değil, C # ile ilgili
The

@theDmi: AMA biraz manipülasyon ve bitmask hakkında. C # bayrak enum kesinlikle bitmask hakkında.
Iğrek.

Ayrıca C ++ 'da da yararlı olabilir. Bakınız: Yığın 1 ve Yığın 2
Igrek.

Bu cevabın, bitsel XOR operatörünün tartışması dışında orijinal soru ile ilgisi yok gibi görünüyor?
Paul R

4

Çok iyi cevaplar var ama bunu daha basit bir şekilde düşünmeyi seviyorum.

if ( 0 != ( x ^ 0x1 ) );

Her şeyden önce. Bir if ifadesi yalnızca bağımsız değişken sıfırsa yanlıştır. Bu, sıfıra eşit olmayan karşılaştırmanın anlamsız olduğu anlamına gelir.

if ( a != 0 );
// Same as
if ( a );

Böylece bizi şöyle bırakır:

if ( x ^ 0x1 );

Biriyle XOR. Bir XOR'un yaptığı temelde farklı bitleri tespit etmektir . Yani, tüm bitler aynıysa 0 döndürür. 0 yanlış olduğundan, yanlış döndürecek tek zaman tüm bitlerin aynı olması demektir. Yani argümanların aynı olması yanlış, farklıysa doğru ... tıpkı operatöre eşit değil gibi .

if ( x != 0x1 );

Aslında, ikisi arasındaki tek fark, !=0 veya 1 ^değerini döndürürken, herhangi bir sayı döndürür, ancak sonucun gerçekliği her zaman aynı olacaktır. Bunu düşünmenin kolay bir yolu.

(b != c) === !!(b ^ c) // for all b and c

Son "sadeleştirme", 1 0x1olan ondalığa dönüştürülür . Bu nedenle ifadeniz şuna eşittir:

if ( x != 1 )

1

^ bir bitsel XOR operatörüdür

X = 1 ise

          00000001   (x)       (decimal 1)
          00000001   (0x1)     (decimal 1)
XOR       00000000   (0x0)     (decimal 0)

burada 0 == (x ^ 0x1)

X = 0 ise

          00000000   (x)       (decimal 0)
          00000001   (0x1)     (decimal 1)
XOR       00000001   (0x1)     (decimal 0)

burada 0! = (x ^ 0x1)

Bir xor b'nin doğruluk tablosu:

a           b        a xor b
----------------------------
1           1           0
1           0           1
0           1           1
0           0           0

Kod sadece


6
Başka bir yinelenen cevap daha yayınlamak gerçekten gerekli mi?
Gizemli

2
başka bir cevap söyleyebilir ancak çoğaltamazsınız. Aklını özür dilerim
akbar ali

1

Standart teknik olabilir kullanılıyor olması, burada, aritmetik olarak daha basit ama içeriksel anlamsızdır da deyim ile değiştirerek bunu karartmak yerine, açıklık için bağlam çevreleyen göründüğü gibi bir deyim tekrarlamak.

Çevredeki kod sık sık başvuruda bulunabilir (x ^ 1)veya test "bit 0 tam tersi ise, bu bit maskesi boş olur mu?" Diye soruyor olabilir.

Koşulun bir şeyin düzenlenmesine neden olduğu göz önüne alındığında, encode()bağlamda 0 bitinin varsayılan durumunun diğer faktörler tarafından ters çevrilmiş olması ve yalnızca bitlerden herhangi birinin varsayılanlarından sapması durumunda ek bilgileri kodlamamız gerekir (normalde sıfır) ).

İfadeyi bağlamdan çıkarır ve ne yaptığını sorarsanız, temeldeki niyeti göz ardı edersiniz. Derleyiciden derleme çıktısına da bakabilir ve bunun 1 ile doğrudan eşitlik karşılaştırması yaptığını görebilirsiniz.


0

Gördüğüm kadarıyla cevapları şimdiye kadar ele almak için basit bir kural özledim XOR. Ne ^ve ne 0xanlama geldiğini (ve if, !=vb.) Ayrıntılara girmeden , ifade 0 != (x^1)şu şekilde yeniden çalışılabilir (a^a)==0:

0 != (x^1) <=> [xor left and right side by 1]
(0^1) != (x^1^1) <=>
1 != x
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.