Örneğin ikinin güç modülünün şu şekilde ifade edilebileceğini biliyoruz:
x % 2 inpower n == x & (2 inpower n - 1).
Örnekler:
x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7
Ya iki sayının genel güçsüzlüğü?
Diyelimki:
x% 7 ==?
Örneğin ikinin güç modülünün şu şekilde ifade edilebileceğini biliyoruz:
x % 2 inpower n == x & (2 inpower n - 1).
Örnekler:
x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7
Ya iki sayının genel güçsüzlüğü?
Diyelimki:
x% 7 ==?
Yanıtlar:
Her şeyden önce, bunu söylemek aslında doğru değil
x % 2 == x & 1
Basit counterexample: x = -1
. Java dahil birçok dilde -1 % 2 == -1
. Yani, %
modulo'nun geleneksel matematiksel tanımı olması gerekmez. Örneğin Java, buna "kalan operatör" diyor.
Bitsel optimizasyonla ilgili olarak, sadece ikinin modulo güçleri bitsel aritmetikte "kolayca" yapılabilir. Genel olarak konuşursak, taban sadece modülo güçler b "kolayca" taban ile yapılabilir b , sayıların gösterimi .
10 tabanı, örneğin olmayan negatif için N
, N mod 10^k
sadece en az önemli alıyork
basamak.
-1 = -1 (mod 2)
, neye ulaştığınızdan emin değilim - IEEE 754'ün geri kalanıyla aynı olmadığını mı söylüyorsunuz ?
(a / b) / b + a % b == a
C-tipi operatörler için a ve b tamsayıları, b sıfırdan farklıdır ve ayrıca abs(a % b) < abs(b)
aynı koşullarla.
(a / b)
* b + a % b == a
.
Bitsel kullanarak 2 ^ i sayılarının modulosunu bulmanın sadece basit bir yolu vardır .
N% 3, n% 7 gibi bağlantıya göre Mersenne vakalarını çözmenin ustaca bir yolu var ... n% 5, n% 255 için özel durumlar ve n% 6 gibi bileşik vakalar var.
2 ^ i durumları için, (2, 4, 8, 16 ...)
n % 2^i = n & (2^i - 1)
Daha karmaşık olanları açıklamak zor. Sadece çok merak ediyorsanız okuyun.
Bu, yalnızca ikisinin (ve genellikle yalnızca pozitif olanların) kuvvetleri için işe yarar çünkü ikili gösterimlerinde yalnızca bir bitin '1'e ayarlanması gibi benzersiz bir özelliğe sahiptirler. Başka hiçbir sayı sınıfı bu özelliği paylaşmadığından, çoğu modül ifadesi için bitsel ve ifadeler oluşturamazsınız.
Etkili algoritmaların var olduğu 2'nin üslerinden başka modüller vardır.
Örneğin, x 32 bit işaretsiz int ise x% 3 = popcnt (x & 0x55555555) - popcnt (x & 0xaaaaaaaa)
"%" Operatörü olmadan Modulo "7"
int a = x % 7;
int a = (x + x / 7) & 7;
&
İkili olarak bitsel ve ( ) operatörünü kullanmamak, yoktur. İspat taslağı:
Diyelim ki öyle bir k değeri var x & k == x % (k + 1)
, ama k! = 2 ^ n - 1 . O zaman x == k ise, ifade x & k
"doğru çalışıyor" gibi görünür ve sonuç k olur . Şimdi, dikkate X == ki : herhangi bir "0" bit olsaydı k , bazı vardır i 0'dan büyük Ki , sadece bu pozisyonlarda 1-bit ile ifade edilebilir. (Örneğin, 1011 (11) ondan 100 (4) çıkarıldığında 0111 (7) olmalıdır, bu durumda i = 4 olduğunda 000 bit 100 olur .) K ifadesinden bir bit ise sıfırdan değişmelidir. ki'yi temsil edecek birine, o zaman bu durumda ki olması gereken x% (k + 1) 'i doğru bir şekilde hesaplayamaz , ancak bitsel boolean ve maske verilen bu değeri üretmenin yolu yoktur.
Bu özel durumda (mod 7),% 7'yi bitsel operatörlerle değiştirebiliriz:
// Return X%7 for X >= 0.
int mod7(int x)
{
while (x > 7) x = (x&7) + (x>>3);
return (x == 7)?0:x;
}
İşe yarıyor çünkü% 8 7 = 1. Açıktır ki, bu kod muhtemelen basit bir x% 7'den daha az verimli ve kesinlikle daha az okunabilir.
Bitwise_and, bitwise_or ve bitwise_not kullanarak herhangi bir bit yapılandırmasını başka bir bit yapılandırmasına değiştirebilirsiniz (yani bu işleçler grubu "işlevsel olarak tamamlanmıştır"). Bununla birlikte, modül gibi işlemler için, genel formül zorunlu olarak oldukça karmaşık olacaktır, onu yeniden oluşturmaya çalışmakla bile uğraşmam.