我们知道,例如两个幂的模数可以这样表达:
x % 2 inpower n == x & (2 inpower n - 1).
示例:
x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7
两个数字的一般非权力怎么样?
让我们说:
x%7 ==?
答案 0 :(得分:61)
首先,说实际上并不准确
x % 2 == x & 1
简单的反例:x = -1
。在许多语言中,包括Java,-1 % 2 == -1
。也就是说,%
不一定是模数的传统数学定义。例如,Java将其称为“余数运算符”。
关于按位优化,只有2的模幂可以在按位算术中“轻松”完成。一般来说,只有基数 b 的模幂才能“轻松”用基数 b 表示数字。
在基数10中,例如,对于非负N
,N mod 10^k
只是取最不重要的k
数字。
答案 1 :(得分:30)
只有一种简单的方法可以使用按位找到2 ^ i个数字的模数。
有一种巧妙的方法来解决Mersenne个案例as per the link,例如n%3,n%7 ...... n%5,n%255和复合案例(例如n%6)有特殊情况。
对于案例2 ^ i,(2,4,8,16 ......)
n % 2^i = n & (2^i - 1)
更复杂的事情很难解释。只有在你非常好奇的时候才能阅读。
答案 2 :(得分:17)
这仅适用于2的幂(并且通常只有正数),因为它们具有在其二进制表示中仅将一个位设置为“1”的唯一属性。因为没有其他类的数字共享此属性,所以不能为大多数模数表达式创建按位和表达式。
答案 3 :(得分:9)
这是一个特殊情况,因为计算机代表基数2中的数字。这是可推广的:
(数字) base %base x
与(number) base 的最后x位数相等。
答案 4 :(得分:5)
除了2的幂之外,还存在有效算法的模数。
例如,如果x是32位unsigned int那么 x%3 = popcnt(x& 0x55555555) - popcnt(x& 0xaaaaaaaa)
答案 5 :(得分:4)
没有“%”运算符的模数“7”
int a = x % 7;
int a = (x + x / 7) & 7;
答案 6 :(得分:3)
不使用二进制中的按位和(&
)运算符,没有。证明草图:
假设有一个值 k ,x & k == x % (k + 1)
,但 k!= 2 ^ n - 1 。然后,如果 x == k ,表达式x & k
似乎“正常运行”,结果是 k 。现在,考虑 x == ki :如果 k 中有任何“0”位,则有一些 i 大于0 > ki 只能在这些位置用1位表示。 (例如,当从中减去100(4)时,1011(11)必须变为0111(7),在这种情况下,当 i = 4 时,000位变为100。)如果来自 k 的表达式必须从0变为1才能表示 ki ,然后才能正确计算 x%(k + 1),其中case应该是 ki ,但是没有办法按位布尔并且在给定掩码的情况下产生该值。
答案 7 :(得分:2)
在这个特定情况下(mod 7),我们仍然可以用位运算符替换%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,而且可读性差。
答案 8 :(得分:1)
使用bitwise_and,bitwise_or和bitwise_not可以将任何位配置修改为另一个位配置(即这些运算符集“功能完整”)。但是,对于像模数这样的操作,通用公式必然会非常复杂,我甚至不愿意尝试重新创建它。
答案 9 :(得分:-1)
只有一种简单的方法可以使用按位来查找2 ^ i数的模数。
根据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,这是一个素数。