按位运算以在Python中产生2的幂

时间:2015-03-04 15:12:47

标签: python bit-manipulation

在语调理论中,一种音乐理论,音符之间的间隔用有理数表示。以2:1的比例加倍频率会使其达到倍频程,1:1的比例不会改变;一致。因此,如果我的间隔 n 大于八度或小于一致(它下降),那么“证明”它是有用的。也就是说,使1≤ n ≤2。我已经在Python中使用以下函数执行此操作:

def justify(n):
    return n / 2 ** floor( log(n,2) )

实际函数涉及分数库,但这可以使用浮点数和整数来完成工作。日志找到2 n 的幂是什么,并且将其向下舍入,以便得到的除数是 n 下最接近的2的幂。我也试过这个:

def justify(n):
    return n / int( '1'.ljust( len( bin(n) ) - 2, '0' ), 2 )

这个只取二进制表示的长度并根据它填充零。当然,这只适用于整数。我想知道是否有任何方法可以通过按位运算来执行此操作。似乎二进制文件很适合2操作的强大功能。至少,我希望看到用某种方式替换2 ** floor( log(n,2) )的方法。如果可以处理花车,可以加分,但我知道这更复杂。

2 个答案:

答案 0 :(得分:3)

math.frexp(x),正如Mark Dickinson在评论中指出的那样,是要走的路:

def justify(n):
    return 2*frexp(n)[0]

它适用于浮点数和整数。

答案 1 :(得分:2)

仅对于整数,您可以通过以下方式稍微狡猾地实现:

def justify(n):
    return n / 1<<(n.bit_length()-1)

我不知道如果没有重大测试它会更快,但使用timeit快速测试显示它的速度是第一个片段的两倍。

但是,将n转换为分子中的浮点数(以获得浮动返回)会使其速度降低到与原始速度相同的速度。

def justify(n):
    return float(n) / 1<<(n.bit_length()-1)

bit_length给出了表示abs(x)所需的最小位数,实际上这个位数实际上比计算所需的位数多一个。

我希望log(n,2)能够针对基数中的2的幂进行大量优化 - 并且它是用C实现的。所以你将无法击败它。

可能会将分母更改为1<<int(log(n,2))可能会比2**方法更好地表现出来......而且似乎提高了约30%

def justify(n):
    return float(n) / (1<<int(log(n,2)))

可以使用按位运算符完全完成:

def justify_bitwise(n):
   int_n = int(abs(n))
   p = 0
   while int_n != 1:
       p += 1
       int_n >>= 1

   return float(n) / (1<<p)

timeit计时为2.16微秒。比使用bit_length

慢一个数量级