学习redis 字典结构,hash找槽位 求槽位的索引值时,用到了 hash值 & sizemask操作,

其后的scan操作涉及扫描顺序逻辑,对同模的槽位 按一定规则扫描!

其中涉及位运算 & 和 %操作之间的关系!故整理学习资料如下:

原文引自:http://blog.sina.com.cn/s/blog_7b7cad23010163vy.html

由于位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度非常快。

按位与(Bitwise AND),运算符号为&

a&b 的操作的结果:a、b中对应位同时为1,则对应结果位也为1、

例如:

10010001101000101011001111000

&           111111100000000

---------------------------------------------

                    10101100000000

对10101100000000进行右移8位得到的是101011,这就得到了a的8~15位的掩码了。

那么根据这个启示,判断一个整数是否是处于 0-65535(2^16) 之间(常用的越界判断):

用一般的 (a >= 0) && (a <= 65535) 可能要两次判断。

改用位运算只要一次:

a & ~((1<< 16)-1)

Ex:
1 0000 0000 0000 0000 //1 << 16 = 65536
0 1111 1111 1111 1111 //(1 << 16) -1 = 65535
1111 11... 0000 0000 0000 0000        //上一步结果~运算,高位都置1,小于65536的位置0, a & 1111 .. 0000 0000 0000 0000             //为真,说明高位有值,大于65535

  

后面的常数是编译时就算好了的。其实只要算一次逻辑与就行了。

常用技巧:

1、 用于整数的奇偶性判断

一个整数a, a & 1 这个表达式可以用来判断a的奇偶性。二进制的末位为0表示偶数,最末位为1表示奇数。使用a%2来判断奇偶性和a & 1是一样的作用,但是a & 1要快好多。

2、 判断n是否是2的正整数冪

(!(n&(n-1)) )&& n

举个例子:

如果n = 16 = 10000, n-1 = 1111

那么:

10000

& 1111

----------

           0

再举一个例子:如果n = 256 = 100000000, n-1 = 11111111

那么:

100000000

&11111111

--------------

0

好!看完上面的两个小例子,相信大家都有一个感性的认识。从理论上讲,如果一个数a他是2的正整数幂,那么a 的二进制形式必定为1000…..(后面有0个或者多个0),那么结论就很显然了。

3、 统计n中1的个数

朴素的统计办法是:先判断n的奇偶性,为奇数时计数器增加1,然后将n右移一位,重复上面步骤,直到移位完毕。

朴素的统计办法是比较简单的,那么我们来看看比较高级的办法。

举例说明,考虑2位二进制数 n=11,里边有2个1,先提取里边的偶数位10,奇数位01,把偶数位右移1位,然后与奇数位相加,因为每对奇偶位相加的和不会超过“两位”,所以结果中每两位保存着数n中1的个数;相应的如果n是四位整数 n=0111,先以“一位”为单位做奇偶位提取,然后偶数位移位(右移1位),相加;再以“两位”为单位做奇偶提取,偶数位移位(这时就需要移2位),相加,因为此时没对奇偶位的和不会超过“四位”,所以结果中保存着n中1的个数,依次类推可以得出更多位n的算法。整个思想类似分治法。
在这里就顺便说一下常用的二进制数:

0xAAAAAAAA=10101010101010101010101010101010

0x55555555 = 1010101010101010101010101010101(奇数位为1,以1位为单位提取奇偶位)

0xCCCCCCCC = 11001100110011001100110011001100

0x33333333 = 110011001100110011001100110011(以“2位”为单位提取奇偶位)

0xF0F0F0F0 = 11110000111100001111000011110000

0x0F0F0F0F = 1111000011110000111100001111(以“8位”为单位提取奇偶位)

0xFFFF0000 =11111111111111110000000000000000

0x0000FFFF = 1111111111111111(以“16位”为单位提取奇偶位)

例如:32位无符号数的1的个数可以这样数:

 
int
count_one(unsigned
long n)
{
//0xAAAAAAAA,0x55555555分别是以“1位”为单位提取奇偶位
n = ((n & 0xAAAAAAAA) >>
) + (n & 0x55555555);

//0xCCCCCCCC,0x33333333分别是以“2位”为单位提取奇偶位
n = ((n & 0xCCCCCCCC) >>
) + (n & 0x33333333);

//0xF0F0F0F0,0x0F0F0F0F分别是以“4位”为单位提取奇偶位
n = ((n & 0xF0F0F0F0) >>
) + (n & 0x0F0F0F0F);

//0xFF00FF00,0x00FF00FF分别是以“8位”为单位提取奇偶位
n = ((n & 0xFF00FF00) >>
) + (n & 0x00FF00FF);

//0xFFFF0000,0x0000FFFF分别是以“16位”为单位提取奇偶位
n = ((n & 0xFFFF0000) >>
) + (n & 0x0000FFFF);

return
n;
}

举个例子吧,比如说我的生日是农历2月11,就用211吧,转成二进制:

n =
11010011

计算n = ((n &
0xAAAAAAAA) >> 1) + (n
& 0x55555555);

得到 n = 10010010

计算n = ((n &
0xCCCCCCCC) >> 2) + (n
& 0x33333333);

得到 n = 00110010

计算n = ((n &
0xF0F0F0F0) >> 4) + (n
& 0x0F0F0F0F);

得到 n = 00000101
-----------------à无法再分了,那么5就是答案了。

4、对于正整数的模运算(注意,负数不能这么算)

先说下比较简单的:

乘除法是很消耗时间的,只要对数左移一位就是乘以2,右移一位就是除以2,传说用位运算效率提高了60%。

乘2^k众所周知:
n<<k。所以你以后还会傻傻地去敲2566*4的结果10264吗?直接2566<<4就搞定了,又快又准确。

除2^k众所周知:
n>>k。

那么 mod
2^k
呢?(对2的倍数取模)

n&((1<<k)-1)

用通俗的言语来描述就是,对2的倍数取模,只要将数与2的倍数-1做按位与运算即可。

好!方便理解就举个例子吧。

思考:如果结果是要求模2^k时,我们真的需要每次都取模吗?

在此很容易让人想到快速幂取模法。


快速幂取模算法

经常做题目的时候会遇到要计算 a^b mod
c
的情况,这时候,一个不小心就TLE了。那么如何解决这个问题呢?位运算来帮你吧。

首先介绍一下秦九韶算法:(数值分析讲得很清楚)

把一个n次多项式f(x) =
a[n]x^n+a[n-1]x^(n-1)+......+a[1]x+a[0]改写成如下形式:

  f(x) =
a[n]x^n+a[n-1]x^(n-1))+......+a[1]x+a[0]

  =
(a[n]x^(n-1)+a[n-1]x^(n-2)+......+a[1])x+a[0]

  =
((a[n]x^(n-2)+a[n-1]x^(n-3)+......+a[2])x+a[1])x+a[0]

  =. .....

  =
(......((a[n]x+a[n-1])x+a[n-2])x+......+a[1])x+a[0].

  求多项式的值时,首先计算最内层括号内一次多项式的值,即

  v[1]=a[n]x+a[n-1]

  然后由内向外逐层计算一次多项式的值,即

  v[2]=v[1]x+a[n-2]

  v[3]=v[2]x+a[n-3]

  ......

  v[n]=v[n-1]x+a[0]

这样,求n次多项式f(x)的值就转化为求n个一次多项式的值。

好!有了前面的基础知识,我们开始解决问题吧

由(a
×b) mod c=( (a mod
c)
× b) mod c.

我们可以将 b先表示成就:

b = a[t]

× 2^t +
a[t-1]×
2^(t-1) + …… + a[0]

× 2^0.
(a[i]=[0,1]).

这样我们由 a^b mod c =
(a^(a[t]
× 2^t +
a[t-1]×
2^(t-1)
+
…a[0]
× 2^0) mod
c.

然而我们求 a^( 2^(i+1) ) mod c=(
(a^(2^i)) mod c)^2 mod c .求得。

具体实现如下:

使用秦九韶算法思想进行快速幂模算法,简洁漂亮

 
//
快速计算 (a ^ p) % m
的值
__int64
FastM(__int64 a, __int64 p, __int64 m)
{
if
(p == ) return ;
__int64 r =
a % m;
__int64 k =
;
while (p > )
{
if
((p & )!=)
{
k = (k * r) % m;
}
r = (r * r) % m;
p >>=
;
}
return
(r * k) % m;
}
 

http://acm.pku.edu.cn/JudgeOnline/problem?id=3070

5、计算掩码

比如一个截取低6位的掩码:0×3F
用位运算这么表示:(1<< 6) -
1
这样也非常好读取掩码,因为掩码的位数直接体现在表达式里。

按位或运算很简单,只要a和b中相应位出现1,那么a|b的结果相应位也为1。就不多说了。

6、子集

  枚举出一个集合的子集。设原集合为mask,则下面的代码就可以列出它的所有子集:

  for (i = mask ; i ; i = (i - 1)
& mask) ;

位运算之——按位与(&)操作——(快速取模算法)的更多相关文章

  1. 【Java基础】14、位运算之——按位与(&)操作——(快速取模算法)

    学习redis 字典结构,hash找槽位 求槽位的索引值时,用到了 hash值 & sizemask操作, 其后的scan操作涉及扫描顺序逻辑,对同模的槽位 按一定规则扫描! 其中涉及位运算 ...

  2. 【转】C语言快速幂取模算法小结

    (转自:http://www.jb51.net/article/54947.htm) 本文实例汇总了C语言实现的快速幂取模算法,是比较常见的算法.分享给大家供大家参考之用.具体如下: 首先,所谓的快速 ...

  3. Raising Modulo Numbers_快速幂取模算法

    Description People are different. Some secretly read magazines full of interesting girls' pictures, ...

  4. Educational Codeforces Round 80 C. Two Arrays(组合数快速取模)

    You are given two integers nn and mm . Calculate the number of pairs of arrays (a,b)(a,b) such that: ...

  5. 09 Memcached 分布式之取模算法的缺陷

    一: Memcached 分布式之取模算法的缺陷(1)假设你有8台服务器,运行中突然down一台,则求余数的底数就7. 后果: key_0%8==0 ,key_0%7==0 =>hist(命中) ...

  6. ShardingSphere-proxy-5.0.0企业级分库分表、读写分离、负载均衡、雪花算法、取模算法整合(八)

    一.简要说明 以下配置实现了: 1.分库分表 2.每一个分库的读写分离 3.读库负载均衡算法 4.雪花算法,生成唯一id 5.字段取模 二.配置项 # # Licensed to the Apache ...

  7. Java 位运算(移位、位与、或、异或、非)

    Java提供的位运算符有:左移( << ).右移( >> ) .无符号右移( >>> ) .位与( & ) .位或( | ).位非( ~ ).位异或( ...

  8. 【Java基础】3、Java 位运算(移位、位与、或、异或、非)

    public class Test { public static void main(String[] args) { // 1.左移( << ) // 0000 0000 0000 0 ...

  9. C#位运算实际作用之操作整型某一位

    1.前言 前几天写了两篇关于c#位运算的文章 c#位运算基本概念与计算过程 C#位运算实际运用 在文中也提到了位运算的实际作用之一就是合并整型,当时引用了一个问题: C# 用两个short,一个int ...

随机推荐

  1. python告诉你ti8 dota2英雄bp

    文章链接:https://mp.weixin.qq.com/s/phJzZEQojndY-iNe77RF_w 恭喜OG成为ti8冠军,很可惜这次偶数年ti8中国队LGD与冠军失之交臂. 上学那会儿还是 ...

  2. Android为TV端助力 集成第三方播放器,实现全屏播放

    下面这Demo链接:Android实现全屏播放,各种格式支持直播,点播,不收费!

  3. 红米手机4A怎么样刷入开发版获得ROOT权限

    小米的手机或平板不同手机型号一般情况官方都提供两个不同系统,可分为稳定版和开发版,稳定版没有提供root权限管理,开发版中就支持了root权限,在很多工作的时候我们需要使用的一些功能强大的app,都需 ...

  4. eclipse如何修改android工程的包名?

    在我们android项目开发到一定的程度时由于需要,我们必须修改一下工程的包名,以便更好的发布我们的项目.但是在这个过程中有时候修改好了之后会出现一些错误.下面由小编一步步教你如何更改包名,和解决出现 ...

  5. MAC MAMP 中安装配置使用 ThinkPHP

    MAMP PRO 是Mac OS X 平台上经典的本地环境应用 MAMP 的专业版.专门为专业的Web开发人员和程序员轻松地安装和管理自己的开发环境. MAMP这几个首字母代表Mac OS X系统上的 ...

  6. MVC文件的上传、删除

    public ActionResult FileUpload()        {            Users users = new Users();            users = ( ...

  7. Python函数(一)之杵臼之交

    Python函数 函数的作用:对功能进行封装,减少重复代码,方便维护,流程清晰明了,易于理解. 函数的结构: def 函数名():      函数体       return语句 函数的返回值: 可以 ...

  8. c/c++ linux 进程 fork wait函数

    linux 进程 fork wait函数 fork:创建子进程 wait:父进程等待子进程结束,并销毁子进程,如果父进程不调用wait函数,子进程就会一直留在linux内核中,变成了僵尸进程. for ...

  9. Kafka 特性

    Kafka 特性 标签(空格分隔): Kafka 支持多个生产者 多个生成者连接Kafka来推送消息,这个和其他的消息队列功能基本上是一样的 支持多个消费者 Kafka支持多个消费者来读取同一个消息流 ...

  10. Django学习开发--笔记一(从零开始)

    创建django项目注: 首先需在python中下载django 命令:pip install django1.任意文件中创建django项目 diango-admin startproject my ...