Algorithm 按位替换模运算符

Algorithm 按位替换模运算符,algorithm,Algorithm,我们知道,例如,2的幂模可以这样表示: x % 2 inpower n == x & (2 inpower n - 1). 示例: x % 2 == x & 1 x % 4 == x & 3 x % 8 == x & 7 两个数的一般非幂怎么样 比如说: x%7=?这仅适用于二次幂(通常仅为正数),因为它们具有唯一的属性,即在二进制表示中只有一位设置为“1”。因为没有其他类别的数字共享此属性,所以不能为大多数模数表达式创建按位and表达式。首先,这样说实

我们知道,例如,2的幂模可以这样表示:

  x % 2 inpower n == x & (2 inpower n - 1).
示例:

x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7 
两个数的一般非幂怎么样

比如说:


x%7=?

这仅适用于二次幂(通常仅为正数),因为它们具有唯一的属性,即在二进制表示中只有一位设置为“1”。因为没有其他类别的数字共享此属性,所以不能为大多数模数表达式创建按位and表达式。

首先,这样说实际上并不准确

x % 2 == x & 1
简单的反例:
x=-1
。在许多语言中,包括Java,
-1%2==-1
。也就是说,
%
不一定是模的传统数学定义。例如,Java称之为“余数运算符”

关于按位优化,在按位算术中只能“轻松地”实现二的模幂。一般来说,只有基数b的模幂可以“容易地”用基数b表示数字

例如,在基数10中,对于非负的
N
N mod 10^k
只取最低有效的
k
位数

工具书类

这是一种特殊情况,因为计算机以基数2表示数字。这是可以概括的:

(数字)基准%basex

与(数字)基的最后x位相等。

如果不使用二进制中的按位and(
&
)运算符,则没有。证据简图:


假设存在一个值k,使得
x&k==x%(k+1)
,但是k!=2^n-1。然后,如果x==k,表达式
x&k
似乎“操作正确”,结果是k。现在,考虑x==k- i:如果k中有任何“0”位,则i i大于0,其中k i只能在这些位置中用1位表示。(例如,当从中减去100(4)时,1011(11)必须变为0111(7),在这种情况下,当i=4时,000位变为100。)如果k表达式中的一位必须从零变为一以表示k-i,则它无法正确计算x%(k+1),在这种情况下,x%(k+1)应为k-i,但是在给定掩码的情况下,按位布尔和无法生成该值。

使用按位和、按位或和按位不,您可以将任何位配置修改为另一位配置(即,这些运算符集“功能完整”)。然而,对于像模这样的运算,一般的公式必然会非常复杂,我甚至不会费心去重新创建它。

除了2的幂之外,还有模存在有效的算法

例如,如果x是32位无符号整数,那么 x%3= popcnt(x&0x555555)-popcnt(x&0xaaaaaa)

在这种特定情况下(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,并且可读性肯定会降低。

没有“%”运算符的模“7”

int a = x % 7;

int a = (x + x / 7) & 7;
只有一种简单的方法可以使用按位查找2^i数的模

有一种巧妙的方法可以解决n%3、n%7。。。 n%5、n%255和n%6等复合情况都有特殊情况

对于案例2^i,(2,4,8,16…)


更复杂的问题很难解释。如果你非常好奇,请阅读。

如果你碰巧在三元体系结构上操作,那么这会改变一些事情……然而,可能性大约为零。我喜欢你的措辞:“这会改变一些事情”@Neil-模和二进制,是非常基本的操作,我猜他们在任何计算机语言中都是一样的。我确实厌倦了不看到语言的发布:虽然我猜通常如果他们不指定,我认为这意味着C++或C。我想知道这是多么真实……对于任何一个努力理解这一点的人,请看一看。哦,在带V8的JS中,我通过使用位运算符获得了非常轻微的性能提升。@JamesKolpack在CPU上执行位运算的速度比模运算快得多。事实上,将寄存器归零的一个常见组装技巧是将其与自身进行异或(因为这一事实)。现在,编译器可能能够优化二次幂的模,但我不知道
-1=-1(mod 2)
,不确定你得到的是什么-你的意思是它是IEEE 754余数?@BlueRaja:mod 2中-1的常见余数是1@BlueRaja:如果你允许负数,你基本上可以确定什么(特别是因为没有提到任何语言)是
(a/b)/b+a%b==a
,对于C型运算符,a和b整数,b非零,并且
abs(a%b)
具有相同的限制条件。@davidthorney-假设你的意思是
(a/b)
*
b+a%b==a
。对于10%2=0不起作用。(10+10/2)&2=15&2=2,同样10%6=4。(10+10/6)&6=11&6=2另外,当你想避免使用模运算时,为什么你要除法?好吧,除法的指令和求余数的指令是一样的。@SriramMurali那是因为你使用了偶数模,当然它不起作用,这是一个解决奇数的方法,就像OP所说的。投票++;很好的链接,谢谢你的参考。我建议让其他人看一看,即使有点复杂,也值得一读。链接是答案中最好的部分。n%2^i=n&(1)
n % 2^i = n & (2^i - 1)