当length为2^n, m & (length-1) 相当于 m % length 的证明

我们都知道在 java 的 hashmap 实现中,对于一个元素在索引数组中位置的确定,使用的方法是: m & (length - 1)。
可是,我们又知道,通常根据hashcode确定元素在数组中的位置时,使用取模的方式,也就是
m % length。

二者哪个更好?结论就是当 length = 2^n 的时候,二者的结果是一样的,而位运算明显会快一些。

那么下面就是对于 当length为2^n, m & (length-1) 相当于 m % length 的这个命题的证明。

一、推理归纳的方式

首先我们要清楚二进制的特点:
2^1 = 10
2^2 = 100
2^3 = 1000
2^n = 1(n个零)

那么如果 2^n - 1 是什么样呢:
2^1 -1 = 01
2^2 -1 = 011
2^3 -1 = 0111
2^n -1 = 0(n个1)

那么,我们可以发现,当 length = 2^n 的时候, m & (length -1)的结果,就是 0 ~ (length -1) 之间的数值,就是相当于 m % length 的结果,而当length != 2^n 的时候,这个特点不成立。大家可以用简单的数字试验一下。

二、公式的推导证明

对于 m % length 的运算,我们总可以把 m 拆分成两个部分,成为 H 部分 和 L 部分,
m % length = (H + L) % length 。
而对于 L 部分,总可以分成和 length 具有相同 二进制位数 的数字。
例如,如果 m = 1010110, length = 100,那么 H = 1010, L = 110,L和length都是3个二进制位数。
(H + L) % length = H%length + L%length
对于 H%length,如果 length 是 2^n ,那么 H%length 就一定是 0,因为 length一定是 10,100,1000, 1后边(n-1)个零,这样的二进制数字。
对于 L%length,那么 L%length就是 0 ~ length -1。如果 length 是 2^n,那么 L%length的结果就是 L & (length -1),例如:
length = 1000 的时候,
length -1 = 0111,
L 和 length 二进制位数相同,只要和 (length -1)进行“&”的运算,得到的就是取模的结果。这主要是因为 length 是 2^n ,例如 n = 3 的时候,1000 就是最大的数字,而减掉 1 后,恰恰是 0,1 互相翻转,变成了 0111,所以用位运算可以处理。如果不是 2^n,就不行了。

所以,如果 length 是 2^n,那么 m%length 的结果,就是 保留 m 的 右边的 和 length-1 的二进制位数一样长度的二进制位数就可以了。
比较绕嘴,有个例子能理解清晰点:
例如, m = 101100110,length = 1000,那么 m%length的计算,就是 保留 m 右边的 3 位二进制就可以了,也就是 110。而保留右边 3 位的方法,就是 m & (length -1)。
从而证明最初的命题。
而如果 length != 2^n,最初对 H 和 L 部分的证明不成立,后边的也不会成立。

以上就是这个命题的两种证明方法,纯属自娱,欢迎指正。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值