Bitsel operatörler ve veya, özel veya değil. Bitsel Operatörler

  • 18.04.2019

Son Güncelleme: 14.09.2018

Bitsel işlemler, özel bir işlem sınıfını temsil eder. Bir sayının tek tek rakamları üzerinde gerçekleştirilirler. Bu planda, sayılar ikili gösterimde kabul edilir, örneğin, 2'de ikili gösterim 10 ve iki basamaklıdır, 7 sayısı 111'dir ve üç basamaklıdır.

Boole işlemleri

    & (boole çarpımı)

    Çarpma işlemi bit bit yapılır ve her iki işlenenin de bit değerleri 1'e eşitse işlem 1 döndürür, aksi takdirde 0 sayısı döndürülür.Örneğin:

    int x1 = 2; //010 int y1 = 5;//101 Console.WriteLine(x1&y1); // 0 int x2 = 4 yazdırır; //100 int y2 = 5; //101 Console.WriteLine(x2 & y2); // 4 yazdırır

    İlk durumda, elimizde 2 ve 5 olmak üzere iki sayı var. 2 ikili formda 010 sayısını ve 5 - 101'i temsil ediyor. Sayıları bit (0 * 1, 1 * 0, 0 * 1) ve a olarak çarpalım. sonuç olarak 000 elde ederiz.

    İkinci durumda, iki yerine, tıpkı 5 sayısı gibi, ilk hanesinde 1 olan 4 sayısına sahibiz, yani sonunda (1 * 1, 0 * 0, 0 * 1) elde ederiz. = 100, yani ondalık biçimde 4 sayısı.

    | (mantıksal ekleme)

    Mantıksal çarpmaya benzer şekilde, işlem ikili sayılar üzerinde de gerçekleştirilir, ancak şimdi bu bitte en az bir sayının bir olması durumunda bir döndürülür. Örneğin:

    int x1 = 2; //010 int y1 = 5;//101 Console.WriteLine(x1|y1); // 7 - 111 yazdırır int x2 = 4; //100 int y2 = 5;//101 Console.WriteLine(x2 | y2); // 5 - 101 yazdırır

    ^ (mantıksal XOR)

    Bu işleme XOR da denir, genellikle basit şifreleme için kullanılır:

    int x = 45; // Şifrelenecek değer - ikili biçimde 101101 int anahtar = 102; // Anahtar bu olsun - ikili biçimde 1100110 int şifreleme = x ^ anahtar; //Sonuç 1001011 veya 75 sayısı olacaktır Console.WriteLine("Şifreli sayı: " +encrypt); int şifresini çöz=şifrele^anahtar; // Sonuç orijinal 45 sayısı olacaktır Console.WriteLine("Şifrelenmiş sayı: " + şifresini çöz);

    Burada yine bitsel işlemler yapılır. Her iki sayı için de mevcut basamağın farklı değerlerine sahipsek, 1, aksi takdirde 0 döndürülür.Böylece, sonuç olarak 9 ^ 5'ten 12 sayısını elde ederiz.Sayıyı deşifre etmek için aynısını uygularız. sonuca operasyon.

    ~ (mantıksal olumsuzlama veya ters çevirme)

    Tüm bitleri tersine çeviren başka bir bitsel işlem: bir bitin değeri 1 ise, o zaman sıfır olur ve bunun tersi de geçerlidir.

    int x = 12; // 00001100 Console.WriteLine(~x); // 11110011 veya -13

Negatif sayıların gösterimi

C# ile imzalı sayılar yazmak için şunu kullanın: ek kod(ikinin tamamlayıcısı), burada en anlamlı bit bir işaret bitidir. Değeri 0 ise, sayı pozitiftir ve ikili gösterimi işaretsiz bir sayınınkiyle aynıdır. Örneğin, 0000 0001'de ondalık sistem 1.

En anlamlı bit 1 ise, negatif bir sayı ile uğraşıyoruz demektir. Örneğin, 1111 1111, ondalık olarak -1'i temsil eder. Buna göre 1111 0011, -13'ü temsil eder.

Pozitif bir sayıdan negatif bir sayı elde etmek için, onu ters çevirmeniz ve bir tane eklemeniz gerekir:

int x = 12; int y = ~x; y += 1; Console.WriteLine(y); // -12

Vardiya işlemleri

Sayıların basamakları üzerinde de kaydırma işlemleri yapılır. Kayma sağa ve sola olabilir.

    x<

    x>>y - x sayısını y basamaklı sağa kaydırır. Örneğin, 16>>1, 16 sayısını (ikili sistemde 10000'dir) bir basamak sağa kaydırır ve ondalık olarak 1000 veya 8 ile sonuçlanır.

Böylece, bir yönde veya başka bir yönde kaydırılması gereken orijinal sayı ikiye bölünürse, aslında, iki ile bir çarpma veya bölme elde edilir. Bu nedenle, doğrudan çarpma veya ikiye bölme yerine benzer bir işlem kullanılabilir.

Etiketler: Xi bit işlemleri, bit düzeyinde işlemler, bit düzeyinde toplama, bit düzeyinde çarpma, sola bit kaydırma, sağa bit kaydırma

giriiş

C dili bazen donanıma yakınlığı nedeniyle makro derleyici olarak anılır. Optimizasyon kullanmazsanız, program kodunun hangi derleme dilinin oluşturduğunu kabaca tahmin edebilirsiniz. Dilin sadeliği ve minimalizmi (dilin sadeliği, dilde programlama kolaylığı ile karıştırılmamalıdır), birçok platformda C'nin tek olduğu gerçeğine yol açmıştır. yüksek seviyeli dil programlama. Bitsel işlemlere genel bir bakış olmadan elbette dil öğrenimi eksik kalacaktır.

Bitsel işlemler, adından da anlaşılacağı gibi, doğrudan bitler üzerinde işlem yapmanızı sağlar. Çok sayıda Bitsel işlemlerin kullanımına ilişkin örnekler, örneğin Henry Warren'ın Programcılar için Algoritmik Hileler kitabında bulunabilir. Burada sadece işlemlerin kendisini ve ilkel algoritmaları ele alıyoruz.

Bitsel AND, OR, NOT, XOR

şunu hatırlatarak başlayayım mantıksal işlemler AND, OR, XOR ve NOT doğruluk tabloları kullanılarak tanımlanabilir

Mantıksal operatör DEĞİL
X X DEĞİL
0 1
1 0

Bit bazında işlemlerde, 1 bit değeri mantıksal doğru, 0 ise yanlış olarak kabul edilir. Bitsel AND (& operatörü) iki sayı alır ve karşılık gelen bitleri mantıksal olarak çarpar. Örneğin, 3 ile 8 mantıksal olarak çarparsak 0 elde ederiz.

Karakter a = 3; karakter b = 8; karakter c = a&b; printf("%d",c);

İkili form 3'te bir baytlık tamsayı olarak

c değişkeninin ilk biti, a'nın ilk biti ile b'nin ilk bitinin mantıksal çarpımına eşittir. Ve böylece her bit için.

00000011
00001000
↓↓↓↓↓↓↓↓
00000000

Buna göre 31 ve 17 sayılarının bitsel çarpımı 17'yi verecektir, çünkü 31 00011111 ve 17 00010001'dir.

00011111
00010001
↓↓↓↓↓↓↓↓
00010001

35 ve 15 sayılarının bitsel çarpımı 3'tür.

00100011
00001111
↓↓↓↓↓↓↓↓
00000011

Bit düzeyinde OR işlemi (işleç |), sayıların karşılık gelen bitlerini taşıma olmadan mantıksal olarak toplaması dışında benzer şekilde çalışır.

Örneğin,

Karakter a = 15; karakter b = 11; karakter c = bir | b; printf("%d",c);

15, 00001111 ve 11 00001011 olduğundan 15 yazdıracak

00001111
00001011
↓↓↓↓↓↓↓↓
00001111

Bitsel ORing 33 ve 11, 33 00100001 ve 11 00001011 olduğundan 43 döndürür

00100001
00001011
↓↓↓↓↓↓↓↓
00101011

Bit düzeyinde olumsuzlama (~ operatörü) tek bir bit için değil, tüm sayı için çalışır. Ters çevirme operatörü, her bit için yanlışı doğruya ve doğruyu yanlışa değiştirir. Örneğin,

Karakter a = 65; charb = ~a; printf("%d", b);

65 01000001 olduğundan -66 çıktısı olacak ve tersi 10111110 olacak

ki bu -66'ya eşittir. Bu arada, bir sayıyı negatif yapmak için bir algoritma: bulmak için ek kod sayıları ters çevrilmeli ve bir tane eklenmelidir.

Karakter a = 107; karakter b = ~a + 1; printf("a = %d, -a = %d", a, b);

Özel VEYA (^ operatörü) geçerlidir bit düzeyinde işlem Xor. Örneğin, sayılar için

karakter = 12; karakter = 85; karakter c = a^b; printf("%d",c);

a 00001100 ve b 01010101 olduğundan 89 çıktısı alınacaktır. Sonuç olarak, 01011001 elde ederiz.

Ara sıra mantıksal operatörler&& ve || & ve | operatörleriyle karıştırılır. Bu tür hatalar kodda uzun süre kalabilir, çünkü bu tür kodlar bazı durumlarda çalışacaktır. Örneğin, 1 ve 0 sayıları için. Ancak C'de sıfır olmayan herhangi bir değer doğru olduğundan, 3 ve 4 sayılarının bit düzeyinde çarpımı, mantıksal çarpmanın doğru döndürmesine rağmen 0 döndürür.

Int a = 3; int b = 4; printf("a & b = %d\n", a & b); //0 yazdırır printf("a && b = %d\n", a && b);//0 değil yazdırır (daha spesifik olarak, 1)

Bit kaydırma işlemleri

İki kaydırma işlemi vardır - bit sola kaydırma (operatör<<) и битовый сдвиг вправо (оператор >>). Bir bit sağa kaydırma, bir sayının bitlerini sağa kaydırır, soldaki sıfırları doldurur. Sola biraz kaydırma tam tersini yapar: bitleri sola kaydırır, sıfırları sağa kaydırır. Sayı dışı bitler atılır.

Örneğin, 5 sayısını 2 konum sola kaydırmak

00000101 << 2 == 00010100

19 sayısını 3 pozisyon sağa kaydır

00010011 >> 3 == 00000010

Mimariden bağımsız olarak (big-endian veya little-endian veya orta-endian), ikili biçimdeki sayılar soldan sağa, daha fazla önemli bit daha az önemli olana. Bit düzeyinde kaydırma, kaydırılacak sayı ve kaydırılacak bit sayısı olmak üzere iki işlenen alır.

int a = 12; printf("%d<< 1 == %d\n", a, a << 1); printf("%d << 2 == %d\n", a, a << 2); printf("%d >> 1 == %d\n", a, a >> 1); printf("%d >> 2 == %d\n", a, a >> 2);

Sağa kaydırma (>>) sola sıfır eklediğinden, tamsayılar için işlem şuna eşittir: tamsayı bölümü yarıya ve sola kaydırma 2 ile çarpılır. Açık bir tür dönüşümü olmadan kayan noktalı bir sayı için bit kaydırma gerçekleştiremezsiniz. Bunun nedeni, c'nin kayan nokta gösterimine sahip olmamasıdır. Ancak, numarayı taşıyabilirsiniz yüzer tip int sonra shift ve geri koymak

Şamandıra b = 10.0f; float c = (float) (*((işaretsiz int*)&b) >> 2); printf("%.3f >> 2 = %.3f", b, c);

Ama elbette 5.0f almayacağız, tamamen farklı bir sayı alacağız.

Kaydırma operatörlerinin özelliği, derleyiciye bağlı olarak işaretli ve işaretsiz sayılarla farklı davranabilmeleridir. Yok canım, negatif bir sayı genellikle bir işaret biti içerir. Sola kaydırma yaptığımızda kaybolabilir, sayı pozitif olur. Bununla birlikte, derleyici kaydırmanın sabit işaretli kalmasını sağlayabilir ve farklı kuralları takip edebilir. Aynı şey sağa kayma için de geçerlidir.

İmzasız int ua = 12; imzalı int sa = -11; printf("ua = %d, ua >> 2 = %d\n", ua, ua >> 2); printf("sa = %d, sa >> 2 = %d\n", sa, sa >> 2); printf("(imzasız) sa = %u, sa >> 2 = %u\n", sa, sa >> 2); printf("sa = %d, ((imzasız) sa) >> 2 = %d", sa, ((işaretsiz) sa) >> 2);

AT bu durum ilk vardiyada her şey istendiği gibi çalışır, çünkü sayı işaretsizdir. İkinci durumda, VSE2013 derleyicisi iz bırakır. Ancak bu sayının işaretsiz olarak temsiline bakarsanız, kaydırma diğer kurallara göre en soldaki bit korunarak gerçekleşir. Son satırda, işaretli bir sayıyı işaretsiz bir sayıya dönüştürürseniz, normal kayma meydana gelir ve sonuç olarak pozitif bir sayı elde ederiz.

Bitsel ve kaydırma operatörleri bir sayının değerini değiştirmez ve yenisini döndürür. Onlar da tıpkı aritmetik operatörler, karmaşık bir görevin parçası olabilir

int a = 10; int b=1; a >>= 3; bir ^= (b<< 3); и т.д.

Örnekler

1. Bir sayının belirli bir bitini belirlemenizi ve değiştirmenizi sağlayan fonksiyonlar yazalım.

Hangi bitin (1 veya 0) n konumunda olduğunu bulmak için mantıksal çarpma kullanırız.

9 sayısı olsun

00001001

Bitin konum 3'e (sıfırdan başlayarak) ayarlanıp ayarlanmadığını bulmamız gerekiyor. Bunu yapmak için, üçüncü hariç tüm bitlerin sıfıra eşit olduğu bir sayı ile çarparız:

00001001 & 00001000 = 00001000

Şimdi 6. konumdaki bitin değerini öğreniyoruz.

00001001 & 01000000 = 00000000

Böylece, sıfıra eşit bir yanıt alırsak, istenen konum sıfır, aksi halde bir olur. İstenen konumda bir biti olan sıfırlardan oluşan bir sayı elde etmek için 1'i istenen bit sayısı kadar sola kaydırırız.

#Dahil etmek #Dahil etmek #Dahil etmek int checkbit(const int değeri, const int konumu) ( int sonucu; if ((değer & (1)<< position)) == 0) { result = 0; } else { result = 1; } return result; } void main() { int a = 3; size_t len = sizeof(int) * CHAR_BIT; size_t i; for (i = 0; i < len; i++) { printf("%d", checkbit(a, i)); } _getch(); }

Fonksiyonda koşulun şöyle yazıldığını unutmayın.

(değer & (1<< position)) == 0

Çünkü parantez olmadan önce sıfır hesaplanacak ve ancak o zaman çarpma işlemi yapılacaktır.

Değer & (1<< position) == 0

Fonksiyon basitleştirilebilir

int checkbit(const int değeri, const int konumu) (dönüş ((değer & (1<< position)) != 0); }

n'inci konumdaki biti bire ayarlayan bir işlev.

Herhangi bir bitin 1 ile mantıksal olarak eklenmesinin 1'e eşit olacağı bilinmektedir. Bu nedenle, n'inci biti ayarlamak için, istenen bit dışındaki tüm bitlerin sıfıra eşit olduğu bir sayıyı mantıksal olarak eklemeniz gerekir. Böyle bir sayının nasıl alınacağı zaten düşünülmüştür.

int setbit(sabit int değeri, sabit int konumu) (dönüş (değer | (1)<< position)); }

n'inci konumdaki biti sıfıra ayarlayan bir işlev.

Bunu yapmak için, sayının n'inci hariç tüm bitlerinin değişmemesi gerekir. Sayıyı, bit sayısı n hariç tüm bitlerin bire eşit olduğu bir ile çarpalım. Örneğin

0001011 & 1110111 = 0000011

Böyle bir maske elde etmek için önce sıfır ve bir birim içeren bir sayı oluşturun ve ardından bunu ters çevirin.

int unsetbit(const int değeri, const int konumu) (dönüş (değer & ~(1)<< position)); }

n'inci bitin değerini tersine çeviren bir işlev.

Bunu yapmak için, özel veya işlevi kullanırız: XOR işlemini, istenen bitin yerinde bir sıfır ve bir içeren bir sayıya uygularız.

int switchbit(const int değeri, const int konumu) (dönüş (değer ^ (1<< position)); }

muayene

#Dahil etmek #Dahil etmek #Dahil etmek int checkbit(const int değeri, const int konumu) (dönüş ((değer & (1<< position)) != 0); } int setbit(const int value, const int position) { return (value | (1 << position)); } int unsetbit(const int value, const int position) { return (value & ~(1 << position)); } int switchbit(const int value, const int position) { return (value ^ (1 << position)); } void printbits(int n) { //CHAR_BIT опеределён в библиотеке limits.h //и хранит число бит в байте для данной платформы size_t len = sizeof(int)* CHAR_BIT; size_t i; for (i = 0; i < len; i++) { printf("%d", checkbit(n, i)); } printf("\n"); } void main() { int a = 3; size_t len = sizeof(int) * CHAR_BIT; size_t i; printbits(a); a = setbit(a, 5); printbits(a); a = unsetbit(a, 5); printbits(a); a = switchbit(a, 11); printbits(a); a = switchbit(a, 11); printbits(a); _getch(); }

bit bayrakları

Sentetik bir örnek düşünün. Diyelim ki üç boole değişkenimiz var ve tüm bu değişkenlere bağlı olarak aynı anda belirli bir değer göstermemiz gerekiyor. Açıkçası, 2 3 olası seçenek olabilir. Bu koşulu bir dal olarak yazıyoruz:

#Dahil etmek int main() ( unsigned char a, b, c; a = 1; b = 0; c = 0; if (a) ( if (b) ( if (c) ( printf("true true"); ) else ( printf("true true false"); ) ) else ( if (c) ( printf("true false true"); ) else ( printf("true false true"); ) ) ) else ( if (b) ( if (c) ( printf("yanlış doğru doğru"); ) else ( printf("yanlış doğru yanlış"); ) ) else ( if (c) ( printf("yanlış yanlış doğru"); ) else ( printf( "yanlış yanlış yanlış"); )) ) _getch(); 0 döndür; )

8 şubemiz var. Şimdi bir koşul daha eklememiz gerektiğini varsayalım. Daha sonra şube sayısı iki katına çıkacak ve programın anlaşılması ve hatalarının ayıklanması daha da zorlaşacaktır. Örneği yeniden yazalım.

Mantıksal değerlerimizin her biri, bit sayısı kadar sola kaydırılır ve mantıksal olarak eklenirse, a, b ve c değerlerine bağlı olarak kendi benzersiz bit kombinasyonumuzu elde ederiz:

#Dahil etmek #Dahil etmek void printbits (int n) ( int i; for (i = CHAR_BIT - 1; i >= 0; i--) ( printf("%d", (n & (1)<< i)) != 0); } printf("\n"); } int main() { unsigned char a, b, c; unsigned char res; a = 1; b = 0; c = 0; res = c | b << 1 | a << 2; printbits(res); a = 0; b = 1; c = 1; res = c | b << 1 | a << 2; printbits(res); a = 1; b = 0; c = 1; res = c | b << 1 | a << 2; printbits(res); _getch(); return 0; }

Bu yaklaşımı görevimizde kullanıyoruz ve dallanmayı anahtarla değiştiriyoruz:

#Dahil etmek int main() ( işaretsiz karakter a, b, c; işaretsiz karakter res; a = 1; b = 0; c = 0; res = c | b<< 1 | a << 2; switch (res) { case 0b00000000: printf("false false false"); break; case 0b00000001: printf("false false true"); break; case 0b00000010: printf("false true false"); break; case 0b00000011: printf("false true true"); break; case 0b00000100: printf("true false false"); break; case 0b00000101: printf("true false true"); break; case 0b00000110: printf("true true false"); break; case 0b00000111: printf("true true true"); break; } _getch(); return 0; }

Bu yöntem sıklıkla farklı programlama dillerinde fonksiyon seçenekleri atamak için kullanılır. Her bayrak kendi benzersiz adını alır ve bunların birleşik değeri, kullanılan tüm bayrakların mantıksal toplamıdır. Örneğin, fcntl kitaplığı.

Bitsel Operatörler

C# bir dizi sağlar bitsel operatörler, C# kullanabileceğiniz görev aralığını genişletiyor. Bitsel operatörler, işlenenlerinin bireysel ikili rakamları (bitleri) üzerinde hareket eder. Yalnızca tamsayı işlenenleri için tanımlanırlar, bu nedenle bool, kayan nokta veya çift veri türlerine uygulanamazlar.

Bu operatörler denir bit düzeyinde, çünkü bir tamsayı değeri oluşturan bitleri test etmek, ayarlamak veya kaydırmak için kullanılırlar. Diğer şeylerin yanı sıra, bitsel operatörler, örneğin cihaz durum bilgilerinin ayrıştırılması dahil olmak üzere çeşitli sistem düzeyinde programlama problemlerini çözmek için kullanılır. C#'da kullanılabilen tüm bitsel operatörler aşağıda listelenmiştir:

Bitsel operatörler AND, OR, özel OR ve NOT

Bit düzeyinde AND, OR, XOR ve NOT operatörleri şu şekilde gösterilir: &, |, ^ ve ~. Onlarla aynı işlevleri yerine getirirler. mantıksal analoglar. Ancak mantıksal operatörlerin aksine, bitsel operatörler bireysel bitler düzeyinde çalışır.

En yaygın uygulamanın bakış açısından, bitsel AND işlemi, tek tek bitleri bastırmanın bir yolu olarak düşünülebilir. Bu, işlenenlerden herhangi birinin herhangi bir biti 0 ise, sonuçtaki karşılık gelen bitin 0'a sıfırlanacağı anlamına gelir. VEYA operatörü bireysel bitleri ayarlamak için kullanılabilir. Bu operatörün herhangi bir işlenenindeki herhangi bir bit 1'e ayarlanırsa, diğer işlenendeki karşılık gelen bit de 1'e ayarlanır. bit düzeyinde XOR operatörü işlenenin ikili basamağını, ancak ve ancak karşılaştırılan işlenenlerin ikili basamakları aşağıdaki örnekte olduğu gibi farklıysa ayarlar. Yukarıdakileri anlamak için aşağıdaki örneği inceleyin:

Şimdi bitsel operatörleri kullanan örnek bir programa bakalım:

Sistemi Kullanmak; System.Collections.Generic kullanarak; System.Linq kullanarak; System.Text'i kullanarak; namespace ConsoleApplication1 ( class Program ( static void Main(string args) ( chet(16); provChet(8)); nechet(16); Console.ReadLine(); ) // Tüm tek sayıları çift sayılara dönüştürme yöntemi // içinde // bitsel operatör & static void chet(int x) ( int sonucu; Console.WriteLine("0'dan (0)'a dönüştürülmüş sayı aralığı:\n",x); for (int i = 0; i) kullanan aralık

Vardiya operatörleri

C#, bir tamsayı değeri oluşturan bitleri belirli bir miktarda sola veya sağa kaydırma yeteneğine sahiptir. Bu operatörler için genel form aşağıdadır:

anlam
değer >> bit sayısı

burada num_bits, belirtilen değerin kaydırıldığı bit sayısıdır.

Sola kaydırma, belirtilen değerdeki tüm bitleri bir konum sola kaydırır ve en az anlamlı biti sıfıra sıfırlar. Sağa kaydırma, belirtilen değerdeki tüm bitleri bir konum sağa kaydırır. İşaretsiz bir tamsayı değeri sağa kaydırılırsa, en anlamlı bit sıfırlanır. Ve işaretli bir tamsayı değeri sağa kaydırılırsa, işaret biti korunur. Negatif sayıları temsil etmek için, tamsayının en anlamlı basamağının 1'e ayarlandığını hatırlayın. Yani, kaydırılan değer negatifse, sağa yapılan her kaydırmada, sayının en anlamlı basamağı 1'e ayarlanır. kaydırılan değer pozitiftir, ardından sağa her kaydırma ile sayının en önemli basamağı sıfırlanır.

Bu sayfadaki bölümler:

Bitsel Operatörler

C# bir dizi sağlar bit düzeyinde C#'ın kullanılabileceği görev aralığını genişleten operatörler. Bitsel operatörler, işlenenlerinin bireysel ikili rakamları (bitleri) üzerinde hareket eder. Yalnızca tamsayı işlenenleri için tanımlanırlar, bu nedenle bool, kayan nokta veya çift veri türlerine uygulanamazlar.

Bu operatörler denir bit düzeyinde, çünkü bir tamsayı değeri oluşturan bitleri test etmek, ayarlamak veya kaydırmak için kullanılırlar. Diğer şeylerin yanı sıra, bitsel operatörler, örneğin cihaz durum bilgilerinin ayrıştırılması dahil olmak üzere çeşitli sistem düzeyinde programlama problemlerini çözmek için kullanılır. C#'da kullanılabilen tüm bitsel operatörler Tablo'da listelenmiştir. 4.1.

Tablo 4.1. Bitsel Operatörler

Operatör Anlamı
& Bit düzeyinde VE
| Bit düzeyinde VEYA
^ Bitsel XOR
>> sağa kaydır
<< Sola kay
~ 1'in tamamlayıcısı (birli NOT operatörü)

Bitsel operatörler AND, OR, özel OR ve NOT

Bit düzeyinde AND, OR, XOR ve NOT operatörleri şu şekilde gösterilir: &, |, ^ ve ~. Yukarıda tartışılan mantıksal karşılıklarıyla aynı işlevleri yerine getirirler. Ancak mantıksal operatörlerin aksine, bitsel operatörler bireysel bitler düzeyinde çalışır. Aşağıda ikili 1'ler ve 0'lar üzerinde bit düzeyinde işlemlerin sonuçları verilmiştir.

p q R & q p | q p ^ q ~p
0 0 0 0 0 1
1 0 0 1 1 0
0 1 0 1 1 1
1 1 1 1 0 0

En yaygın uygulamanın bakış açısından, bitsel AND işlemi, tek tek bitleri bastırmanın bir yolu olarak düşünülebilir. Bu, işlenenlerden herhangi birinin herhangi bir biti 0 ise, sonuçtaki karşılık gelen bitin 0'a sıfırlanacağı anlamına gelir. Örneğin:

1101 0011
1010 1010
&_________
1000 0010

Aşağıdaki program örneği, tek sayıları çift sayılara dönüştürmek için bitsel & operatörünün nasıl kullanılacağını gösterir. Bunun için sayının en az anlamlı basamağını sıfırlamak yeterlidir. Örneğin, 9 sayısı aşağıdaki ikili forma sahiptir: 0000 1001. Bu sayının en az anlamlı bitini sıfırlarsanız, 8 sayısı olur ve ikili biçimde 0000 1000 olur.

// Sayıyı çift yapmak için bitsel AND operatörünü uygulayın.
Sistemi kullanarak;
sınıf MakeEven(
statik boşluk Main() (
kısa numara; ushort i;
için(i=1; ben<= 10; i++) {
sayı = ben;

num = (ushort) (sayı & 0xFFFE);
Console.WriteLine("en az anlamlı basamağı sıfırladıktan sonraki sayı: "
+ sayı + "n");
}
}
}

1 numara
düşük basamak sıfırlamasından sonra num: 0
2 numara

3 numara
düşük haneli sıfırlamadan sonra num: 2
sayı: 4

5 numara
düşük haneli sıfırlamadan sonra num: 4
sayı: 6

7 numara
düşük haneli sıfırlamadan sonra num: 6
sayı: 8

9 numara
düşük basamak sıfırlamasından sonra num: 8
sayı: 10
düşük haneli sıfırlamadan sonra num: 10

Bitsel AND operatöründe kullanılan onaltılık değer 0xFFFE aşağıdaki ikili forma sahiptir: 1111 1111 1111 1110. Böylece, bitsel AND işlemi, sıfırlanan en az anlamlı bit dışında, num'un sayısal değerindeki tüm ikili basamakları değiştirmeden bırakır. sıfır. Sonuç olarak, çift sayılar herhangi bir değişikliğe uğramaz ve tek sayılar 1 azalır ve çift olur.

Bitsel operatör AND, tek bir bitin set veya reset durumunu belirlemek için de kullanışlıdır. Aşağıdaki program örneği, bir sayının tek olup olmadığını belirler.

// olup olmadığını belirlemek için bitsel AND operatörünü uygulayın
// sayının tek olup olmadığı.
Sistemi kullanarak;
sınıf IsOdd(
statik boşluk Main() (
kısa numara;
sayı = 10;
if((sayı & 1) == 1)
Console.WriteLine("Çıkış yapılmıyor.");
sayı = 11;
if((sayı & 1) == 1)
Console.WriteLine(num + " tek sayıdır.");
}
}

İşte bu programın çıktısı neye benziyor.

11 tek sayıdır.

Yukarıdaki programdaki if deyimlerinin her ikisi de num ve 1'in sayısal değerleri üzerinde bitsel AND işlemi gerçekleştirir. bir ikili 1 içeriyorsa, num & 1 bitsel işlemin sonucu 1'dir. Aksi takdirde, sıfırdır. Bu nedenle if ifadesi yalnızca test edilen sayı tek ise başarılı olabilir.

Bitsel operatörü kullanarak ayrı bitlerin durumunu kontrol etme yeteneği & kontrol edilen bayt değerinin ayrı bitlerinin ikili biçimde verildiği bir program yazmak için kullanılabilir. Aşağıda böyle bir program yazmanın bir yolu gösterilmektedir.

// Bir baytı oluşturan bitleri göster.
Sistemi kullanarak;
sınıf ShowBits (
statik boşluk Main() (
int t;
bayt değeri;
değer = 123;
for(t=128; t > 0; t = t/2) (


}
}
}

Bu programı çalıştırmak aşağıdaki sonucu verir.

0 1 1 1 1 0 1 1

Yukarıdaki programdaki for döngüsünde, val değerinin her biti, bitin ayarlanmış mı yoksa temiz mi olduğunu görmek için bitsel AND operatörü kullanılarak test edilir. Ayarlanmışsa 1 sayısı görüntülenir ve silinirse 0 sayısı görüntülenir.

Bitsel OR operatörü, bireysel bitleri ayarlamak için kullanılabilir. Bu operatörün herhangi bir işlenenindeki herhangi bir bit 1'e ayarlanırsa, diğer işlenendeki karşılık gelen bit de 1'e ayarlanır. Örneğin:

1101 0011
1010 1010
|_________
1111 1011

Bitsel VEYA operatörünü kullanarak, tek sayıları çift sayılara dönüştüren bir programın yukarıdaki örneğini, çift sayıların tek sayıya dönüştürüldüğü aşağıdaki ters örneğe kolayca çevirebilirsiniz.

// Sayıyı tek yapmak için bitsel OR operatörünü kullanın.
Sistemi kullanarak;
sınıf MakeOdd(
statik boşluk Main() (
kısa numara;
ushort i;
for(i = 1; ben<= 10; i++) {
sayı = ben;
Console.WriteLine("sayı:" + sayı);
sayı = (ushort)(sayı | 1);
Console.WriteLine("en az anlamlı basamağı ayarladıktan sonraki sayı: "
+ sayı + "n");
}
}
}

Bu programı çalıştırmanın sonucu aşağıdaki gibidir.

1 numara
düşük sırayı ayarladıktan sonra num: 1
2 numara

3 numara
düşük rakamı ayarladıktan sonra num: 3
sayı: 4

5 numara
düşük sırayı ayarladıktan sonra num: 5
sayı: 6

7 numara
düşük sırayı ayarladıktan sonra num: 7
sayı: 8

9 numara
düşük rakamı ayarladıktan sonra num: 9
sayı: 10
düşük sırayı ayarladıktan sonra num: 11

Yukarıdaki program, 1, en az anlamlı bit seti ile bir ikili değer verdiğinden, num ve 1'in her sayısal değeri üzerinde bit düzeyinde VEYA işlemi gerçekleştirir. 1 ve diğer herhangi bir değer üzerinde bit düzeyinde OR işleminin bir sonucu olarak, diğer tüm bitler değişmeden kalırken ikincisinin en az anlamlı biti ayarlanır. Bu nedenle, orijinal değer çift ise, elde edilen sayısal değer tektir.

Bitsel XOR operatörü, işlenenin bit konumunu ancak ve ancak karşılaştırılan işlenenlerin bit konumları aşağıdaki örnekte olduğu gibi farklıysa ayarlar.

0111 1111
1011 1001
^_________
1100 0110

Bitsel XOR operatörü, çeşitli durumlarda kullanışlı olan ilginç bir özelliğe sahiptir. Bu nedenle, önce X'in bir değeri üzerinde başka bir Y değeri üzerinde bit düzeyinde özel VEYA işlemi gerçekleştirirseniz ve daha sonra önceki işlemin sonucu ve Y değeri üzerinde aynı işlemi yaparsanız, X'in orijinal değeri dönecektir. aşağıdaki kod parçacığında olduğu anlamına gelir

R1=X^Y;
R2=R1^Y;

R2 değişkeninin değeri, X değişkeninin değeri ile aynı olur. Bu nedenle, aynı değeri kullanan ardışık iki bitsel XOR işlemi sonucunda orijinal değer elde edilir. Bu işlemin bu özelliği, bu mesajın karakterleri üzerinde XOR işlemini kullanarak bir mesajı kodlamak ve kodunu çözmek için bir tamsayı değerinin bir anahtar görevi gördüğü basit bir şifreleme programı yazmak için kullanılabilir. Düz metni şifreli metne kodlamak için ilk kez XOR işlemi ve şifreli metni düz metne çözmek için ikinci kez gerçekleştirilir. Tabii ki, bu tür şifreleme, kolayca tahmin edilebildiği için pratik bir değere sahip değildir. Bununla birlikte, aşağıdaki programda olduğu gibi, bitsel XOR operatörlerini kullanmanın sonuçlarını göstermek için ilginç bir örnek olarak hizmet eder.

// Bitsel XOR operatörünün kullanımını gösterin.

Sistemi kullanarak;
sınıf kodlaması(
statik boşluk Main() (
karakter ch1 = "H";
karakter ch2 = "i" ;
karakter ch3 = "!";
int anahtarı = 88;
Console.WriteLine("Orijinal mesaj: " + ch1 + ch2 + ch3) ;
// Mesajı şifrele,
ch1 = (char)(ch1^key);
ch2 = (char)(ch2^key);
ch3=(char)(ch3^key);
Console.WriteLine("Şifreli mesaj: " + ch1 + ch2 + ch3);
// Mesajın şifresini çöz.
ch1 = (char)(ch1^key);
ch2 = (char)(ch2^key);
ch3=(char)(ch3^key);
Console.WriteLine("Kod çözülmüş mesaj: " + ch1 + ch2 + ch3);
}
}

Orijinal mesaj: Hey!
Şifreli mesaj: Qly
Kodu çözülen mesaj: Merhaba!

Görüldüğü gibi iki sıra bitsel XOR işlemi gerçekleştirilmesi sonucunda şifresi çözülmüş bir mesaj elde edilmektedir. (Doğal olarak güvenilmez olduğundan, bu tür şifrelemenin pratik bir değeri olmadığını tekrar hatırlayın.)

Bit düzeyinde tekli NOT operatörü (veya 1'in tümleyen operatörü), işlenendeki tüm bitlerin durumunu tersine çevirir. Bu nedenle, eğer bir A tamsayı değeri, 1001 0110 ikili basamaklarının bir kombinasyonuna sahipse, o zaman ~A bitsel işlemin bir sonucu olarak, 0110 1001 ikili basamaklarının bir kombinasyonuna sahip bir değer elde edilir.

Aşağıdaki program örneği, bir sayıyı ve 1'in tamamlayıcısını ikili olarak yazdırmak için bit düzeyinde NOT operatörünün nasıl kullanılacağını gösterir.

// Bit düzeyinde tekli NOT operatörünün kullanımını gösterin.
Sistemi kullanarak;
classNotDemo(
statik boşluk Main() (
sbyte b = -34;
for(int t=128; t > 0; t = t/2) (

}
Console.WriteLine();
// tüm bitleri ters çevir b = (sbyte) ~b;
b = (byte)~b;
for(int t=128; t > 0; t = t/2) (
if((b & t) != 0) Console.Write("1 ");
if((b & t) == 0) Console.Write("0 ");
}
}
}

Bu programın çıktısı aşağıda gösterilmiştir.

1 1 0 1 1 1 1 0
0 0 1 0 0 0 0 1

Vardiya operatörleri

C#, bir tamsayı değeri oluşturan bitleri belirli bir miktarda sola veya sağa kaydırma yeteneğine sahiptir. C#, bu amaç için aşağıdaki iki bit kaydırma operatörünü tanımlar.

<< Сдвиг влево
>> sağa kaydır

Bu operatörler için genel form aşağıdadır:

"sayı_bitleri" değeri
değer » sayı_bitleri

nerede sayı_bitleri belirtilen bit sayısıdır anlam.

Sola kaydırma, belirtilen değerdeki tüm bitleri bir konum sola kaydırır ve en az anlamlı biti sıfıra sıfırlar. Sağa kaydırma, belirtilen değerdeki tüm bitleri bir konum sağa kaydırır. İşaretsiz bir tamsayı değeri sağa kaydırılırsa, en anlamlı bit sıfırlanır. Ve işaretli bir tamsayı değeri sağa kaydırılırsa, işaret biti korunur. Negatif sayıları temsil etmek için, tamsayının en anlamlı basamağının 1'e ayarlandığını hatırlayın. Yani, kaydırılan değer negatifse, sağa yapılan her kaydırmada, sayının en anlamlı basamağı 1'e ayarlanır. kaydırılan değer pozitiftir, ardından sağa her kaydırma ile sayının en önemli basamağı sıfırlanır.

Sola ve sağa kaydırırken, aşırı ikili rakamlar kaybolur. Vardiya sırasında kaybedilen bitleri geri yüklemek mümkün değildir, çünkü verilen dava döngüsel değildir.

Aşağıdaki, sola ve sağa kaydırmanın etkisini açıkça gösteren bir örnek programdır. Bu örnek ilk önce ilk tamsayı değerini 1'e ayarlar. Bu, bu değerin en az anlamlı bitinin ayarlandığı anlamına gelir. Daha sonra bu tam sayı değeri art arda sekiz kez sola kaydırılır. Her kaydırmadan sonra, verilen değerin en az anlamlı sekiz biti çıktılanır. İşlem daha sonra tekrarlanır, ancak bu sefer 1 sekizinci basamak konumuna ayarlanır ve esas olarak 128 tamsayı değeri ayarlanır, bu daha sonra arka arkaya sekiz kez sağa kaydırılır.

// Vardiya operatörlerinin kullanımını gösterin.
Sistemi kullanarak;
classShiftDemo(
statik boşluk Main() (
aralık = 1;
for(int ben = 0; ben< 8; i++) {
for(int t=128; t > 0; t = t/2) (
if((val & t) != 0) Console.Write("1 ");
if((val & t) == 0) Console.Write("0 ");
}
Console.WriteLine();
değer = değer<< 1; // сдвиг влево
}
Console.WriteLine() ;
değer = 128;
for(int ben = 0; ben< 8; i++) {
for(int t=128; t > 0; t = t/2) (
if((val & t) != 0) Console.Write("1 ");
if((val & t) == 0) Console.Write("0 ");
}
Console.WriteLine();
değer = değer >>1; // sağa kaydır
}
}
}

Bu programı çalıştırmanın sonucu aşağıdaki gibidir.

0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0
0 0 0 0 1 0 0 0
0 0 0 1 0 0 0 0
0 0 1 0 0 0 0 0
0 1 0 0 0 0 0 0
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1

İkili basamaklar, sayıların 2 kuvvetine temsiline karşılık gelir ve bu nedenle kaydırma operatörleri, tamsayı değerlerini 2 ile çarpmak veya bölmek için kullanılabilir. Bu nedenle, sağa kaydırırken, tamsayı değeri iki katına çıkar ve kaydırma yaparken sola, yarıya iner. Tabii ki, tüm bunlar yalnızca bir yönde veya diğerinde kaydırma yaparken aşırı bitler kaybolmadığında doğrudur. Aşağıda ilgili bir örnek bulunmaktadır.

// 2 ile çarpma ve bölme için kaydırma operatörlerini uygulayın.
Sistemi kullanarak;
sınıf MultDiv(
statik boşluk Main() (
intn;
n = 10;
Console.WriteLine("n değişkeninin değeri: " + n) ;
// 2 ile çarp.
n = n<< 1;
"işlemler n = n * 2: " + n) ;
// 4 ile çarp.
n = n<< 2;
Console.WriteLine("n değişkeninin değeri: sonra " +
"işlemler n = n * 4: " + n) ;
// 2'ye böl.
n = n >> 1;
Console.WriteLine("n değişkeninin değeri: sonra " +
"işlemler n = n / 2:" + n) ;
// 4'e böl.
n = n >> 2;
Console.WriteLine("n değişkeninin değeri: sonra " +
"işlemler n = n / 4:" + n) ;

Console.WriteLine();

// n değişkenini başlangıç ​​durumuna ayarla,
n = 10;
Console.WriteLine("n değişkeninin değeri: " + n);
// 2 ile otuz kez çarpın.
n = n<< 30; // данные теряются
Console.WriteLine("n'den sonraki değişkenin değeri" +
"30 basamak sola kaydır: " + n);
}
}

Bu programın çıktısı aşağıdadır.

Değişken değeri n: 10
n değişkeninin değeri: işlemden sonra n = n * 2: 20
n değişkeninin değeri: işlemden sonra n = n * 4: 80
n değişkeninin değeri: işlemden sonra n = n / 2: 40
n değişkeninin değeri: işlemden sonra n = n / 4: 10
Değişken değeri n: 10
30 basamak sola kaydırıldıktan sonra n değişkeninin değeri: -2147483648

Yukarıdaki sonucun son satırına dikkat edin. 10 tamsayı değeri art arda otuz kez sola kaydırıldığında, bitler sayıların int gösteriminin dışına kaydırıldığı için bilgi kaybolur. Bu durumda, işaret olarak kullanılan en önemli bitteki kaymanın bir sonucu olarak, 1 olduğu ve dolayısıyla bu sayısal değer olduğu için, negatif olduğu da ortaya çıkan tamamen "kullanılamaz" bir değer elde edilir. negatif olarak yorumlanmalıdır.Bu örnek, 2 ile çarpmak veya bölmek için vardiya operatörlerini kullanırken çok dikkatli olunmasını açıkça göstermektedir (İmzalı ve imzasız veri türleri hakkında daha fazla bilgi için Bölüm 3'e bakın.)

Bitsel Bileşik Atama Operatörleri

Tüm ikili bit düzeyinde operatörler, bileşik atama işlemlerinde kullanılabilir. Örneğin, aşağıdaki iki ifadede, x'e XORing x'in orijinal değerinin ve 127 sayısal değerinin sonucu atanır.

x=x^127;
x^ = 127;