下面说的第几,都是指从左往右
1 << i 的意思就是指,将1移动到第 ( i + 1 ) 位上
比如 i = 0,那么 1 << i = 1,因为要移动到第1位上,所以是1
同理,i = 2, 1 << i = 4,把1移动到第三位上,按照二进制表示就是 100,正好是4
我们注意到,这个1 << i 貌似和 pow(2,i)非常相像
比如 1 << 0 = 1 = pow(2,0)
1 << 2 = 4 = pow(2,2)
那按照规律来说, 1 << i 和 pow(2,i) 应该是等价的
下面说下他们的优缺点(位运算):
优点: 由于电脑是二进制运算,故位运算更符合电脑的运行,因此运行速度快,在一些算法比赛中常用,比如 a = b / 2,这种代码,可以等价替换乘 a = b >> 1(<< 左移是乘2,>> 右移是除2)
缺点: 位运算符号实际上并不常用,而这也导致对其运算顺序的忽略
例如: mid = l + (r - l) >> 1 按照正常思路来说,这是没错的啊,不就是防止r + l 越界的mid实现吗?
这就是容易让人忽略的点,这个+ 的运算优先级事实上是大于 >> 的,这就导致上式
等价为 mid = (l + r - l) >> 1 = r >> 1 = r / 2,这和我们想要的完全不搭边啊,这种就是位运算的缺陷,不常见,导致运算顺序优先级掌握不住,所以,在使用位运算时,一定不要吝惜括号,不能图简洁就省括号,正确的需要是 mid = l + (r - l >> 1),不能把>>1放到括号外面
还有个非常细微的点,不常见,但一旦碰到很难想到
如上所述,1 << i 和pow(2,i)可以算等价,那么 1 << 31 和 pow(2,31) 等价不等价??
这就是非常容易忽略的点,可能我们觉得1 << 31不就是2^31吗,错了,还有符号位!!!
计算机是二进制,最高位是符号位,这就导致,1000..0,这个最高位的1,实际上是表示当前数是负数,实际上,1 << 31是 -2^31,而不是2 ^31,2^31就超了int,而pow(2,31)却实实在在的是2^31
总结:
位运算速度更快,在不会超过符号的情况下,适合替代简单的乘除2 但需要考虑到符号位
保证万无一失的前提下,可以用1 << i位运算,发现可能到达临界点,就稳妥点用pow,pow是不会出现误差的