按位取代模数运算符
我们知道例如两个权的模可以这样表示:
x % 2 inpower n == x & (2 inpower n - 1).
例子:
x % 2 == x & 1 x % 4 == x & 3 x % 8 == x & 7
两个数字的一般无力呢?
我们说:
x%7 ==?
首先,这样说实际上是不准确的
x % 2 == x & 1
简单的反例: x = -1
。 在很多语言中,包括Java, -1 % 2 == -1
。 也就是说, %
不一定是模的传统math定义。 例如,Java将其称为“余数运算符”。
关于按位优化,只有两个模幂可以“轻松”地按位算术完成。 一般来说,只有基数b的模数能够“容易地”用数字的基数b表示来完成。
以10为底,例如,对于非负N
, N mod 10^k
只是取最小的k
数字。
参考
- JLS 15.17.3剩余操作员%
- Wikipedia / Modulo Operation
这只适用于两个幂(通常只是正数),因为它们具有在其二进制表示中只有一个位设置为'1'的唯一属性。 由于没有其他类别的数字共享此属性,因此不能为大多数模数expression式创build按位和expression式。
只有一个简单的方法来find2 ^我的数字模数按位。
根据n%3,n%7等链接 ,有一种巧妙的方法来解决Mersenne案件。对于n%5,n%255和复合案例如n%6有特殊情况。
对于情况2 ^ i,(2,4,8,16 …)
n % 2^i = n & (2^i - 1)
更复杂的是很难解释。 只有在你非常好奇的时候才能阅读。
这是一个特殊的情况,因为计算机代表基数为2的数字。这是可以概括的:
(数字) 基数 %base x
等于(数字) 基的最后x个数字。
存在有效algorithm存在的2的幂以外的模。
例如,如果x是32位无符号整数,那么x%3 = popcnt(x&0x55555555) – popcnt(x&0xaaaaaaaa)
for x % 7 = ? x % 7 == (x+x/7) & 7
在java中完美工作。
int a = x % 7 ; int a = (x+x/7)&7;
两个陈述都是一样的。
在二进制中不使用按位和( &
)运算符,没有。 示意图:
假设有一个值k ,使得x & k == x % (k + 1)
,但是k!= 2 ^ n – 1 。 那么如果x == k ,则expression式x & k
似乎“正常运行”,结果是k 。 现在考虑x == ki :如果k中有任何“0”位,那么有一些i大于0,那么ki在这些位置上只能用1位表示。 (例如,当100(4)已经被减去时,1011(11)必须变成0111(7),在这种情况下,当i = 4时000位变为100)。如果来自k的expression式的位必须从零到一个来表示ki ,那么它不能正确地计算x%(k + 1) ,在这种情况下它应该是ki ,但是没有办法按位布尔值并且在给定掩码的情况下产生该值。
使用bitwise_and,bitwise_or和bitwise_not,可以将任何位configuration修改为另一位configuration(即这些操作符集“function完整”)。 但是,对于像模数这样的操作来说,通用公式必然是相当复杂的,我甚至不打算重新创build它。
在这个特定的情况下(mod 7),我们仍然可以用位运算符replace%7:
// Return X%7 for X >= 0. int mod7(int x) { while (x > 7) x = (x&7) + (x>>3); return (x == 7)?0:x; }
它的工作原理是8%7 = 1。显然,这个代码可能比简单的x%7效率低,而且可读性也更差。
只有一个简单的方法来find2 ^我的数字模数按位。
根据n%3,n%7等链接,有一种巧妙的方法来解决Mersenne案件。对于n%5,n%255和复合案例如n%6有特殊情况。
对于情况2 ^ i,(2,4,8,16 …)
n%2 ^ i = n&(2 ^ i – 1)
更复杂的是很难解释。 只有在你非常好奇的时候才能阅读。
@ Murali任何这样的方法n%[(2 ^ 16)+1] = 65537。 我的意思是n%(2 ^ k)+1这是一个素数。