Birkaç gün önce StackExchange üyesi Anto bit bilge operatörler için geçerli kullanımları sordu . Kaymanın tamsayıları ikisinin gücü ile çarpmaktan ve bölmekten daha hızlı olduğunu söyledim. StackExchange üyesi Daemin, sağa kaymanın negatif sayılarla ilgili sorunlar sunduğunu belirterek karşılık verdi.
Bu noktada, vardiya operatörlerini işaretli tamsayılarla kullanmayı hiç düşünmemiştim. Öncelikle bu tekniği düşük seviye yazılım geliştirmede kullandım; bu nedenle her zaman işaretsiz tamsayılar kullandım. C, işaretsiz tamsayılarda mantıksal kaymalar gerçekleştirir. Doğru bir mantıksal kaydırma gerçekleştirirken işaret bitine dikkat edilmez. Boşaltılan bitler sıfırlarla doldurulur. Bununla birlikte, C, işaretli bir tamsayı sağını kaydırırken aritmetik bir kaydırma işlemi gerçekleştirir. Boş bitler işaret biti ile doldurulur. Bu fark, negatif bir değerin, sıfıra doğru kısaltılmak yerine sonsuza yuvarlanmasına neden olur; bu, işaretli tam sayı bölümünden farklı bir davranıştır.
Birkaç dakikalık düşünce birinci dereceden bir çözümle sonuçlandı. Çözelti, kaydırmadan önce koşullu olarak negatif değerleri pozitif değerlere dönüştürür. Bir değer, vardiya işlemi gerçekleştirildikten sonra koşullu olarak negatif biçimine dönüştürülür.
int a = -5;
int n = 1;
int negative = q < 0;
a = negative ? -a : a;
a >>= n;
a = negative ? -a : a;
Bu çözümün sorunu, koşullu atama ifadelerinin genellikle en az bir atlama komutuna çevrilmesidir ve atlama komutları, her iki komut yolunun kodunu çözmeyen işlemcilerde pahalı olabilir. Bir talimat boru hattını iki kez yeniden astarlamak zorunda kalmak, bölme üzerinde kayma ile elde edilen herhangi bir performans kazancında iyi bir çökme sağlar.
Yukarıdakilerle birlikte, Cumartesi günü şartlı görev sorununun cevabı ile uyandım. Bir aritmetik vardiya işlemi gerçekleştirirken yaşadığımız yuvarlama problemi, sadece ikisinin tamamlayıcı gösterimi ile çalışırken ortaya çıkar. Kişinin kompleman temsili ile gerçekleşmez. Sorunun çözümü, vardiya işlemini gerçekleştirmeden önce bir ikinin tamamlayıcı değerini bir kişinin tamamlayıcı değerine dönüştürmeyi içerir. Daha sonra kişinin tamamlayıcı değerini ikinin tamamlayıcı değerine dönüştürmeliyiz. Şaşırtıcı bir şekilde, bu operasyon setini, vardiya işlemini gerçekleştirmeden önce negatif değerleri şartlı olarak dönüştürmeden gerçekleştirebiliriz.
int a = -5;
int n = 1;
register int sign = (a >> INT_SIZE_MINUS_1) & 1
a = (a - sign) >> n + sign;
İkinin tamamlayıcı negatif değeri, çıkartılarak kişinin tamamlayıcı negatif değerine dönüştürülür. Flip tarafında, bir kişinin kompleman negatif değeri bir ikisini tamamlayarak negatif değerine dönüştürülür. Yukarıda listelenen kod, işaret biti ikisinin tamamlayıcısından tamamlayıcısına dönüştürmek için kullanıldığından işe yarar . Yalnızca negatif değerler işaret bitlerini ayarlayacaktır; bu nedenle, a pozitif olduğunda değişken işareti sıfıra eşit olacaktır .
Yukarıdakilerle birlikte, yukarıdaki hileler gibi hileler çantanıza girmiş gibi düşünebilir misiniz? En sevdiğiniz bit bilge kesmek nedir? Her zaman yeni performans odaklı bit bilge kesmek için arıyorum.