Bitsel operatörlerin gerçek dünya kullanım durumları [kapalı]


225

Aşağıdaki bitsel operatörlerin bazı gerçek dünya kullanım durumları nelerdir?

  • VE
  • XOR
  • DEĞİL
  • VEYA
  • Sol / Sağ kaydırma

1
Onları ilk öğrendiğimde, sadece düşük seviyeli c için kullanıldıklarını hatırlıyorum ... ama o zamandan beri araç kutusu ile girdiler ve "yüksek seviyeli" programlama da dahil olmak üzere sık sık kullanıyorum. Onlar artık benim için + ve * gibi.
Meşe

2
@Anon .: Aklımda, gerçek dünyanın, bitsel operatörlerin en belirgin kullanımı olan düşük seviyeli programlama dışında bir şey ifade etmesi gerekiyordu.
Olivier Lalonde



Bir permütasyonda eksik bir numara bulmak için ikili XOR'u
Janac Meena

Yanıtlar:


217
  • Bit alanları (bayraklar) Durumu
    birkaç "evet veya hayır" özelliği ile tanımlanan bir şeyi temsil etmenin en etkili yoludur. EKL iyi bir örnektir; diyelim ki 4 ayrı izin (okuma, yazma, yürütme, değişiklik politikası), atık 4 yerine 1 baytta saklamak daha iyidir. Daha fazla rahatlık için bunlar birçok dilde numaralandırma türleriyle eşleştirilebilir.

  • Bağlantı noktaları / soketler üzerinden iletişim
    Her zaman sağlama sayıları, eşlik, durdurma bitleri, akış kontrol algoritmaları vb. bir zaman.

  • Sıkıştırma, Şifreleme
    Bunların her ikisi de büyük ölçüde bitsel algoritmalara bağlıdır. Bak Sıkıştırılmalı bir örnek için algoritma - her şey bitler halinde, bayt değil.

  • Sonlu Durum Makinaları
    Yazılımda da bulunabilmelerine rağmen, öncelikle bir parça donanıma gömülü türden bahsediyorum. Bunlar doğada kombinatoryal - onlar tam anlamıyla mantık kapıları bir grup aşağı "derlenmiş" alıyor olabilirler, onlar gibi ifade edilebilir zorunda AND, OR, NOTvb

  • Grafikler Burada, bu operatörlerin grafik programlamada kullanıldığı her alana girmek için yeterli alan yoktur. XOR(veya ^) burada özellikle ilginçtir, çünkü aynı girdiyi ikinci kez uygulamak birinciyi geri alır. Eski GUI'ler, maliyetli yeniden çizimlere olan ihtiyacı ortadan kaldırmak için seçim vurgulama ve diğer kaplamalar için buna güveniyordu. Yavaş grafik protokollerinde (yani uzak masaüstü) hala yararlıdırlar.

Bunlar benim ilk ortaya koyduğum birkaç örnekti - bu pek kapsamlı bir liste değil.


Merhaba @Aaronaught, Gerçekten bizimle çok iyi bir bilgi paylaştınız. Bitwise Operator'un gerçek dünya vakaları hakkında daha fazla bilgi edinmek istiyorum. Referansınızı bizimle paylaşmak ister misiniz, daha fazla bilgi edinmek gerçekten yararlı olacaktır.
Heena Hussain

Bitsel işlemler vektörleştirilebilir hesaplamalar için faydalı mıdır?
Aaron Franke

47

Tuhaf mı?

(value & 0x1) > 0

İki (çift) ile bölünebilir mi?

(value & 0x1) == 0

3
Dil değerinize bağlı olarak & 0x1> 0 değer olarak ayrıştırılabilir & (0x1> 0)
leeeroy

3
@leeeroy - Yeterince doğru. Bazı ebeveynler eklendi.
Seth

Modern optimize ediciler, (% 2 değeri!! = 0 gibi ifadeleri otomatik olarak yukarıdaki ifadelere dönüştürür. godbolt.org/z/mYEBH4
Ferrarezi

26

Bir CMS için bir güvenlik modeli uygulamada bitsel işlemler kullandım. Kullanıcıların uygun gruplarda olmaları halinde erişebilecekleri sayfalar vardı. Bir kullanıcı birden çok grupta olabilir, bu nedenle kullanıcı grupları ile sayfa grupları arasında bir kavşak olup olmadığını kontrol etmemiz gerekiyordu. Bu nedenle, her gruba benzersiz bir 2 güç gücü tanımlayıcısı atadık, örneğin:

Group A = 1 --> 00000001
Group B = 2 --> 00000010
Group C = 3 --> 00000100

Bu değerleri OR VEYA birlikte tutarız ve değeri sayfa ile (tek int olarak) depolarız. Bir sayfaya A ve B grupları tarafından erişilebiliyorsa, 3 değerini (ikili dosyada 00000011 olan) sayfalara erişim kontrolü olarak saklarız. Aynı şekilde, hangi gruplarda olduklarını göstermek için bir kullanıcıyla ORed grup tanımlayıcılarının bir değerini saklarız.

Bu nedenle, belirli bir kullanıcının belirli bir sayfaya erişip erişemediğini kontrol etmek için, değerleri birlikte AND yapmanız ve değerin sıfır olmadığından emin olmanız yeterlidir. Bu kontrol, tek bir komutla, döngü yok, veritabanı gidiş-dönüşleri olmadan uygulandığı için çok hızlıdır.


26

Bireysel bitler olarak saklanan bayraklarla ilgili bazı yaygın deyimler.

enum CDRIndicators {
  Local = 1 << 0,
  External = 1 << 1,
  CallerIDMissing = 1 << 2,
  Chargeable = 1 << 3
};

unsigned int flags = 0;

Ücretli bayrağını ayarlayın:

flags |= Chargeable;

CallerIDMissing bayrağını temizle:

flags &= ~CallerIDMissing;

CallerIDMissing ve Chargeable'ın ayarlanıp ayarlanmadığını test edin:

if((flags & (CallerIDMissing | Chargeable )) == (CallerIDMissing | Chargeable)) {

}

24

Düşük seviyeli programlama buna iyi bir örnektir. Örneğin, bir donanım parçasının istediğiniz şeyi yapmasını sağlamak için bellek eşlemeli bir kayıt defterine belirli bir bit yazmanız gerekebilir:

volatile uint32_t *register = (volatile uint32_t *)0x87000000;
uint32_t          value;
uint32_t          set_bit   = 0x00010000;
uint32_t          clear_bit = 0x00001000;

value = *register;            // get current value from the register
value = value & ~clear_bit;   // clear a bit
value = value | set_bit;      // set a bit
*register = value;            // write it back to the register

Ayrıca htonl()ve ve operatörleri htons()kullanılarak uygulanır ( endianitesi (Bayt sırası) ağ sırasıyla eşleşmeyen makinelerde ):&|

#define htons(a) ((((a) & 0xff00) >> 8) | \
                  (((a) & 0x00ff) << 8))

#define htonl(a) ((((a) & 0xff000000) >> 24) | \
                  (((a) & 0x00ff0000) >>  8) | \
                  (((a) & 0x0000ff00) <<  8) | \
                  (((a) & 0x000000ff) << 24))

7
Herkes makinede konuşmuyor. İkinci örneğiniz ne yapıyor?
ChaosPandion

7
htons()ve htonl()a shortveya a'yı longana bilgisayar ( h) endianitesinden ağ ( n) bayt sırasına değiştirmek için POSIX işlevleridir .
Carl Norum

O (logN) işlemlerinde bit tersini yapmak için benzer bir yöntem kullanabilirsiniz.
Mike DeSimone

lol bunu ilk gördüğümde montaj olduğunu düşündüm!
0x499602D2

htonl()32 bitlik bir intdeğer için değil mi? longbirçok dilde 64 bit anlamına gelir.
Aaron Franke

21

Bunları örneğin paketlenmiş renk değerlerinden RGB (A) değerleri almak için kullanıyorum.


Ve gerçekten hızlı bir şekilde yapıyor!
Callum Rogers

C # 'da, okunabilirlik ve hız için gerçekten en iyi çözüm olduğu durumlardan biridir.
CaptainCasey

4
Makinemde, (a & b) >> c5 kattan daha hızlı a % d / e(ARGB'yi temsil eden bir int'ten tek bir renk değeri elde etmenin her iki yolu). Sırasıyla, 1 milyar yineleme için 6.7'ler ve 35.2'ler.
Benji XVI

@BenjiXVI C # bunun için derleyici optimizasyonuna sahiptir. Bir hız farkını gözlemlemenizin nedeni, C # ' %da Modül operatörü değil, Kalan operatörü olmasıdır. Pozitif değerler için eşdeğerdir, ancak negatif olanlarla farklılık gösterirler. Uygun kısıtlamaları sağlarsanız ( örneğin uintyerine int) geçerseniz , iki örnek aynı hızda olmalıdır.
Aaron Franke

üzgünüm uzun zaman olduđunu biliyorum. Her bir RGB değerini elde etmek için nasıl kullanılacağına dair bir örnek gösterebilir misiniz?
Jinx

14

Bir sürü boolean bayrakım olduğunda hepsini bir int'de saklamayı seviyorum.

Onları bitsel-AND kullanarak çıkarıyorum. Örneğin:

int flags;
if (flags & 0x10) {
  // Turn this feature on.
}

if (flags & 0x08) {
  // Turn a second feature on.
}

vb.


23
Umarım bunlar aslında gerçek kodunuzda sabittir ve sihirli sayılar değildir :)
Earlz

1
Düşük seviyeli olmayan dünyada boole bayrakları kullanmanın bir örneği, çeşitli GUI platformlarıyla bir şeyler yapmaktır. Örneğin, kapatmak için my_button.Style | = STYLE_DISABLED kullanabilirsiniz.
MauriceL

1
Bu konunun dil bilincinde olmadığını biliyorum, ancak C bunu bit alanlarıyla yapmanın kolay bir yolunu sunuyor, böylece böyle şeyler kullanabilirsiniz if (flags.feature_one_is_one) { // turn on feature }. ANSI C standardında olduğundan taşınabilirlik sorun olmamalı.
polandeer

bu kod snippet'inin ne yaptığını, bayrakların neden başlatılmadığını, "hepsini bir
int'de sakla

13

& = VE:
Belirli bitleri maskeleyin.
Görüntülenmesi veya gösterilmemesi gereken belirli bitleri tanımlıyorsunuz. 0xFF ve x bir bayttaki tüm bitleri temizlerken, 0xFF x'i değiştirmez. 0x0F, alt uçtaki bitleri görüntüler.

Dönüştürme:
Bit kimliğine sahip daha kısa değişkenleri daha uzun değişkenlere dökmek için bitleri ayarlamak gerekir, çünkü int'deki -1 değeri 0xFFFFFFFF, uzunluğunda -1 ise 0xFFFFFFFFFFFFFFFF'dir. Kimliği korumak için dönüşümden sonra bir maske uygularsınız.

| = VEYA Bitleri
ayarla. Bitler, önceden ayarlanmışlarsa bağımsız olarak ayarlanır. Birçok veri yapısında (bit alanı) IS_HSET = 0, IS_VSET = 1 gibi bayraklar bulunur. Bayrakları ayarlamak için IS_HSET | IS_VSET (C ve montajda bu okumak çok uygundur)

^ = XOR
Aynı veya farklı bitleri bulun.

~ = DEĞİL
Uçları çevirin.

Tüm olası yerel bit işlemlerinin bu işlemler tarafından uygulanabileceği gösterilebilir . Eğer isterseniz sadece bir bit işlemi ile bir ADD talimatı uygulayabilirsiniz.

Bazı harika kesmek:

http://www.ugcs.caltech.edu/~wnoise/base2.html
http://www.jjj.de/bitwizardry/bitwizardrypage.html


Aşağıda, süper hızlı matematik işlemleri için AS3'te bitsel işleçlerin kullanılmasına ilişkin mükemmel örnekler veren bir bağlantı verilmiştir (ancak çoğu dile uygulanabilir): lab.polygonal.de/2007/05/10/bitwise-gems-fast- integer-math
Ocak'ta

Bence "DEĞİL" olmalı = ~, değil |=, VEYA.
Mike DeSimone

İçin & = AND- Neden neden ben byte değiştirilmemiş bir sürümünü almak istiyorum isteyeyim, tüm bitleri temizlemek istiyorum, ve daha düşük kemirmek ilgisi neyim ki?
confused00

1
@ confused00 doğru, bir sonucu geçersiz kılmanın daha hızlı / basit yolu xorkendisidir. Alt kırıntıyı çıkarmak isteyebileceğiniz birkaç nedeni düşünebilirim. Özellikle bu düşük kırıntı veri yapısının bir parçasıysa ve bunu maske olarak veya ORbaşka bir yapı ile kullanmak istiyorsanız .
James

11

Şifreleme tüm bitsel işlemlerdir.


4
Gerçekten mi? Şifreleme uygulamalarının bitsel op'ları kullanması muhtemeldir, ancak şifreleme algoritmaları bit gösterimleri açısından değil, genellikle sayısal terimlerle açıklanır.
Constantin

1
Peki bunları uygulamaktan başka algoritmalarla ne yaparsınız? Merak ediyorum.
özyinelemeli

2
@Constantin: Örneğin, DES'in nasıl uygulandığının açıklamasına bakın: ( en.wikipedia.org/wiki/…
Wayne Conrad

1
@recursive, Benimle ilgili kişisel olarak soruyorsanız - ne şifreleme algoritmaları tasarlamıyorum ne de bunları uyguluyorum. Ancak insanlar teorik zayıflıklar için analiz etmek gibi birçok şey yaparlar.
Constantin

@Constantin Bu bakabilirsiniz, bu şekilde şifreleme algoritmaları tipik tarif edilmiştir ne (bir parçası) birçok arasında sadece bir örnektir: en.wikipedia.org/wiki/Substitution_box
SyntaxT3rr0r

9

Verileri karma yapmak için hızlı ve kirli bir yol olarak kullanabilirsiniz.

int a = 1230123;
int b = 1234555;
int c = 5865683;
int hash = a ^ b ^ c;

8

^Bir PLC ile seri iletişim için bir sağlama toplamı hesaplamak için yaklaşık üç dakika önce bitwise-XOR ( ) kullandım ...


7

Bitsel ve baytın belirli bir bölümünü maskelemek / çıkarmak için kullanılır.

1 Bayt değişkeni

 01110010
&00001111 Bitmask of 0x0F to find out the lower nibble
 --------
 00000010

Özellikle vardiya operatörü (<< >>) genellikle hesaplamalar için kullanılır.


7

Bu, bitmap görüntüsündeki renkleri bayt formatında okumak için bir örnektir

byte imagePixel = 0xCCDDEE; /* Image in RRGGBB format R=Red, G=Green, B=Blue */

//To only have red
byte redColour = imagePixel & 0xFF0000; /*Bitmasking with AND operator */

//Now, we only want red colour
redColour = (redColour >> 24) & 0xFF;  /* This now returns a red colour between 0x00 and 0xFF.

Umarım bu küçük örnekler yardımcı olur ....


6

Günümüz modern dilinin soyutlanmış dünyasında, çok fazla değil. Dosya G / Ç, akla gelen kolay bir dosyadır, ancak bu zaten uygulanmış olan bir şey üzerinde bitsel işlemler uygular ve bitsel işlemler kullanan bir şey uygulamaz. Yine de, kolay bir örnek olarak, bu kod bir dosyadaki salt okunur özniteliğin kaldırılmasını gösterir (böylece c # 'da yeni bir FileStream belirterek FileMode.Create belirterek kullanılabilir):

//Hidden files posses some extra attibutes that make the FileStream throw an exception
//even with FileMode.Create (if exists -> overwrite) so delete it and don't worry about it!
if(File.Exists(targetName))
{
    FileAttributes attributes = File.GetAttributes(targetName);

    if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
        File.SetAttributes(targetName, attributes & (~FileAttributes.ReadOnly));

    File.Delete(targetName);
}

Özel uygulamalara gelince, işte son bir örnek: Dağıtılmış uygulamamızın bir kurulumundan diğerine güvenli mesaj göndermek için bir "mesaj merkezi" oluşturdum. Temel olarak, Gelen Kutusu, Giden Kutusu, Gönderilmiş vb.Ile birlikte e-postaya benzer, ancak okundu bilgileriyle teslimat garantisi de vardır, bu nedenle "gelen kutusu" ve "gönderilen" öğelerinin ötesinde ek alt klasörler de vardır. Bunun ne anlama geldiği, "gelen kutusunda" veya "gönderilen klasörde" ne olduğunu genel olarak tanımlamam için bir gereklilikti. Gönderilen klasörde neyin okunduğunu ve neyin okunmadığını bilmem gerekiyor. Okunmamış olanlardan neyin alındığını ve nelerin alınmadığını bilmem gerekiyor. Bu bilgiyi, yerel bir veri kaynağını filtreleyen ve uygun bilgileri görüntüleyen dinamik bir nerede cümlesi oluşturmak için kullanıyorum.

Enum nasıl bir araya getirilir:

    public enum MemoView :int
    {
        InboundMemos = 1,                   //     0000 0001
        InboundMemosForMyOrders = 3,        //     0000 0011
        SentMemosAll = 16,                  //     0001 0000
        SentMemosNotReceived = 48,          //     0011
        SentMemosReceivedNotRead = 80,      //     0101
        SentMemosRead = 144,                //     1001
        Outbox = 272,                       //0001 0001 0000
        OutBoxErrors = 784                  //0011 0001 0000
    }

Bunun ne yaptığını görüyor musunuz? (&) "Inbox" numaralandırma değeri InboundMemos ile anding tarafından, InboundMemosForMyOrders gelen kutusunda olduğunu biliyorum.

Şu anda seçili olan klasör için bir görünüm tanımlayan filtreyi oluşturan ve döndüren yöntemin haşlanmış bir sürümü:

    private string GetFilterForView(MemoView view, DefaultableBoolean readOnly)
    {
        string filter = string.Empty;
        if((view & MemoView.InboundMemos) == MemoView.InboundMemos)
        {
            filter = "<inbox filter conditions>";

            if((view & MemoView.InboundMemosForMyOrders) == MemoView.InboundMemosForMyOrders)
            {
                filter += "<my memo filter conditions>";
            }
        }
        else if((view & MemoView.SentMemosAll) == MemoView.SentMemosAll)
        {
            //all sent items have originating system = to local
            filter = "<memos leaving current system>";

            if((view & MemoView.Outbox) == MemoView.Outbox)
            {
                ...
            }
            else
            {
                //sent sub folders
                filter += "<all sent items>";

                if((view & MemoView.SentMemosNotReceived) == MemoView.SentMemosNotReceived)
                {
                    if((view & MemoView.SentMemosReceivedNotRead) == MemoView.SentMemosReceivedNotRead)
                    {
                        filter += "<not received and not read conditions>";
                    }
                    else
                        filter += "<received and not read conditions>";
                }
            }
        }

        return filter;
    }

Son derece basit, ancak tipik olarak bitsel işlemler gerektirmeyen bir soyutlama düzeyinde düzgün bir uygulama.


4

Base64 kodlaması buna bir örnektir. Base64 kodlaması, ikili verileri e-posta sistemleri (ve diğer amaçlar) üzerinden gönderilmek üzere yazdırılabilir bir karakter olarak göstermek için kullanılır. Base64 kodlaması, 8 bit baytlık bir diziyi 6 bit karakter arama dizinlerine dönüştürür. Bit işlemleri, kaydırma ve 'veya' değil ', Base64 kodlama ve kod çözme için gerekli bit işlemlerini uygulamak için çok yararlıdır.

Bu elbette sayısız örnekten sadece bir tanesidir.



4

Genellikle bitsel işlemler çarpma / bölme işleminden daha hızlıdır. Yani bir değişkeni x'i 9 ile çarpmanız gerekiyorsa, bunu x<<3 + xbirkaç döngüden daha hızlı yaparsınız x*9. Bu kod bir ISR'nin içindeyse, yanıt süresinden tasarruf edersiniz.

Benzer şekilde, bir diziyi dairesel kuyruk olarak kullanmak istiyorsanız, biraz akıllıca işlemlerle kontrolleri sarmak daha hızlı (ve daha zarif) olacaktır. (dizi boyutunuz 2 güç olmalıdır). Örn:, eklemek / silmek istiyorsanız tail = ((tail & MASK) + 1)yerine kullanabilirsiniz tail = ((tail +1) < size) ? tail+1 : 0.

Ayrıca, bir hata işaretinin birden çok hata kodunu bir arada tutmasını istiyorsanız, her bit ayrı bir değer tutabilir. Her bir hata kodu ile VE olarak bir kontrol olarak yapabilirsiniz. Bu Unix hata kodlarında kullanılır.

Ayrıca bir n-bit bitmap gerçekten harika ve kompakt bir veri yapısı olabilir. Eğer n boyutunda bir kaynak havuzu tahsis etmek isterseniz, mevcut durumu temsil etmek için bir n-bit kullanabiliriz.


3

Hiç kimse sabit nokta matematikten bahsetmemiş gibi görünüyor.

(Evet, ben yaşlıyım, tamam mı?)


3

Sayı x2'nin gücü mü? (Örneğin, bir sayacın artırıldığı algoritmalarda kullanışlıdır ve bir eylemin yalnızca logaritmik defa yapılması gerekir)

(x & (x - 1)) == 0

Tam sayının en yüksek biti xhangisidir? (Bu, örneğin 2'den büyük minimum gücü bulmak için kullanılabilir x)

x |= (x >>  1);
x |= (x >>  2);
x |= (x >>  4);
x |= (x >>  8);
x |= (x >> 16);
return x - (x >>> 1); // ">>>" is unsigned right shift

1Tam sayının en düşük biti xhangisidir? (2'ye bölünebilir sayısını bulmanıza yardımcı olur.)

x & -x

LHS imzasız tipe dökülerek C'de imzasız sağ kaydırma yapılır. Son formülünüz en düşük [set] bitini bulamaz, X'in 2 gücü olup olmadığını kontrol eder. En düşük set bitini bulmak için yapın x & -x.
Ocak'ta Potatoswatter

Hmm, haklısın, bir şekilde x & -x'i ilk snippet ile değiştirdim, düzenleme için thx
Dimitris Andreou

3

Bitsel operatörler, uzunluğu 2 olan dizileri döngüye sokmak için kullanışlıdır. Bahsedildiği gibi, bitsel operatörler son derece kullanışlıdır ve Bayraklar , Grafikler , Ağ Oluşturma , Şifreleme'de kullanılır . Sadece bu da değil, aynı zamanda son derece hızlı. Benim kişisel favori kullanım için döngü bir dizi olmadan Koşullamalar . Sıfır dizin tabanlı bir diziniz olduğunu varsayalım (örneğin, ilk öğenin dizini 0) ve süresiz olarak döngü yapmanız gerektiğini varsayalım . Süresiz demek istediğim, ilk öğeden sonuncuya ve ilk öğeye geri dönmek demek. Bunu uygulamanın bir yolu:

int[] arr = new int[8];
int i = 0;
while (true) {
    print(arr[i]);
    i = i + 1;
    if (i >= arr.length) 
        i = 0;
}

Eğer kaçınmak istiyorsanız bu en basit yaklaşımdır eğer açıklamada, kullanabilirsiniz modülü şöyle bir yaklaşım:

int[] arr = new int[8];
int i = 0;
while (true) {
    print(arr[i]);
    i = i + 1;
    i = i % arr.length;
}

Bu iki yöntemin aşağı tarafı, modül operatörünün pahalı olmasıdır, çünkü tamsayı bölünmesinden sonra bir kalıntı arar. Ve ilk yöntem her yinelemede bir if ifadesi çalıştırır . Ancak bitsel operatör ile dizinizin uzunluğu 2 güç ise, (bitsel ve) operatörünü 0 .. length - 1kullanarak kolayca bir dizi oluşturabilirsiniz . Bunu bilerek, yukarıdaki kod&i & length

int[] arr = new int[8];
int i = 0;
while (true){
    print(arr[i]);
    i = i + 1;
    i = i & (arr.length - 1);
}

İşte böyle çalışır. Olarak ikili biçimde 1 ile çıkarılır 2 gücü her sayı sadece olanlarla ifade edilir. Örneğin, ikili dosyada 3 11, 7 111, 15 1111ve benzeri, fikri anlarsınız. Şimdi, &sadece ikili olanlardan oluşan bir sayıya karşı herhangi bir sayı alırsanız ne olur ? Diyelim ki bunu yapıyoruz:

num & 7;

Eğer numdaha küçük veya 7'ye eşitse, sonuç 1 ile numbit &olan her bitin kendisinin olması olacaktır. Eğer num7'den daha büyük, sırasında &operasyon bilgisayarın tabii sonra sıfır olarak kalacak başta sıfırları 7 's ele alacağız &sadece sondaki parçası olmaya devam edecektir operasyon. 9 & 7İkili durumda olduğu gibi

1001 & 0111

sonuç, ondalık sayıda 1 olan ve dizideki ikinci öğeye yönelik olan 0001 olacaktır.


Dizinizin uzunluğu 2'lik bir güçse, metnin yarısına ilk ifadeniz konmalıdır. Bu hileyi kullanmak çok ciddi bir sınırlamadır. Şahsen ben bu zaten uygulamak olmaz, kod daha anlamak zordur eğer veya mod yaklaşımlar.
Jan Doggen

@ JanDoggen Haklısın, ilk cümleye koyacağım. Dizi iki güç gelince, benim deneyimime göre bu işe yaradı birkaç kez vardı. Muhtemelen ağ ve grafiklerle ilgili olduğu için.
kullanıcı3552161

1
Bu yazının amacı, bitsel operatörlerin 0, 1, 2, 3, 0, 1, 2 ... sayı dizileri oluşturmak için yararlı olduğunu göstermekti.
user3552161

2

Onları çoklu seçim seçenekleri için kullanıyorum, bu şekilde 10 veya daha fazla yerine sadece bir değer saklıyorum


2

sql ilişkisel modelinde de kullanışlı olabilir, diyelim ki aşağıdaki tablolarınız var: BlogEntry, BlogCategory

traditonally, bir BlogEntryCategory tablosu kullanarak aralarında bir nn ilişkisi oluşturabilir veya BlogEntry'de bayraklı numaralarla yaptığınız gibi birden çok BlogCategory kaydına bağlanmak için bir değer kullanabileceğiniz BlogCategory kayıtları olmadığında, çoğu RDBMS'de de bu 'işaretli' sütunda seçim yapmak için çok hızlı bir operatör ...


2

Bir mikrodenetleyicinin Çıkışlarının bazı bitlerini değiştirmek istediğinizde, ancak yazılacak kayıt bir bayt olduğunda, bunun gibi bir şey yaparsınız (sözde kod):

char newOut = OutRegister & 0b00011111 //clear 3 msb's
newOut = newOut | 0b10100000 //write '101' to the 3 msb's
OutRegister = newOut //Update Outputs

Tabii ki, birçok mikrodenetleyici her biti ayrı ayrı değiştirmenize izin verir ...


bunun hangi dil olması gerekiyor?
Carson Myers

@Carson: Dil yok, bu sahte kod. Aslında bunu birkaç yıl önce yaptım, ama sanırım C'de bunu yapmak kolay. Başlıklar için teşekkürler, daha açık hale getirmek için güncelleyeceğim
Emilio M Bumachar

Yorumları değiştirmek için cevabı düzenledim, böylece vurgulama çok geçmemişti. Ve anlıyorum, o C olabileceğini düşündüm ama ben 0b ... gösterimini kullanılan dilek C. sunulmuştu
Carson Myers

2

Sayı modunuzu (%) belirli bir 2 gücü hesaplamak istiyorsanız yourNumber & 2^N-1, bu durumda aynı olanı kullanabilirsiniz yourNumber % 2^N.

number % 16 = number & 15;
number % 128 = number & 127;

Bu büyük olasılıkla sadece 2 ^ N çok büyük bir temettü ile modül operasyonu için bir alternatif olmak yararlıdır ... Ama o zaman bile bile modül 2.0 üzerinde hız artışı .NET 2.0 üzerinde benim test ihmal edilebilir. Modern derleyicilerin zaten böyle optimizasyonlar yaptığından şüpheleniyorum. Bunun hakkında daha fazla bilen biri var mı?


Derleyiciler bu optimizasyonu kullanırlar ... ancak optimizasyonu bilmiyorsan, tam güç 2 olan bir bölücü seçemeyebilirsin.
Ben Voigt

Bu duruma bağlıdır. C # 'da bu aslında farklı sonuçlar üretir %, Kalan işlemde olduğu gibi negatiflere farklı davranırlar. Ancak, eğer geçerseniz uintiçin %, C # derleyicisi aslında bitwise kullanarak makine kodu üretecek VE ikinci argüman ikisinin bir ön bilinen güç olduğunda.
Aaron Franke

1

Rol tabanlı erişim kontrol sistemlerinde kullanıldığını gördüm.



1

Çoğunlukla bitsel operasyonlar için kullanılırlar (sürpriz). PHP kod tabanında bulunan birkaç gerçek dünya örneği.

Karakter kodlaması:

if (s <= 0 && (c & ~MBFL_WCSPLANE_MASK) == MBFL_WCSPLANE_KOI8R) {

Veri yapıları:

ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK;

Veritabanı sürücüleri:

dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READONLY);

Derleyici uygulaması:

opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;

1

C programlamaya ilk başladığımda, doğruluk tablolarını ve bunların hepsini anladım, ancak bu makaleyi okuyana kadar aslında nasıl kullanılacağını tıklamadı http://www.gamedev.net/reference/articles/article1563.asp (gerçek hayattan örnekler verir)


1
Hayır, aynı değil. C'de, eğer x == 1ve y == 2sonra x || y1 olarak x | ydeğerlendirir ve 0 olarak değerlendirir. Ayrıca neden hiçbir şekilde x^trueüstündür !x. Daha fazla yazım, daha az deyimsel ve eğer xolmazsa boolgüvenilmez.
David Thornley

oh bekle .. evet, bu benim açımdan aptalca .. Bugün düz düşünemiyorum.
Ocak'ta Earlz

x | y, 3 olarak değerlendirir (değiştir: nvm, uzakta düzenlenen bir şeye başvurduğunuzu görüyorum!)
Pod

1
@DavidThornley: Bir olgu x^truedaha üstündür !xolan some->complicated().member->lookup ^= true; tekli operatörlerden hiçbir bileşik atama sürümü vardır.
Ben Voigt

1

Bunun bitsel olduğunu düşünmüyorum, ama Ruby'nin Array'ı normal tamsayı bitsel operatörleri aracılığıyla ayarlanmış işlemleri tanımlar. Yani [1,2,4] & [1,2,3] # => [1,2]. Benzer şekilde a ^ b #=> set differenceve için a | b #=> union.


1

Tower Of Hanoi doğrusal çözümü sorunu çözmek için bitsel işlemleri kullanır.

public static void linear(char start, char temp, char end, int discs)
{
    int from,to;
    for (int i = 1; i < (1 << discs); i++) {
        from = (i & i-1) % 3;
        to = ((i | i-1) + 1) % 3;
        System.out.println(from+" => "+to);
    }
}

Bu çözümün açıklaması burada bulunabilir

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.