按位运算产生 Python 中的 2 的幂
Bitwise operations to produce power of two in Python
在纯音调理论中,一种音乐理论,音符之间的间隔用有理数表示。以 2:1 比率将频率加倍可将其提高一个八度,而 1:1 比率则没有变化;齐声。因此,如果我有一个大于八度或小于同音(下降)的音程 n,'justify' 就很有用。也就是说,要使 1 ≤ n ≤ 2。我在 Python 中使用以下函数执行此操作:
def justify(n):
return n / 2 ** floor( log(n,2) )
实际的功能涉及到分数库,但这可以用浮点数和整数来完成工作。对数计算 2 n 的幂次方,然后 floor 将其向下舍入,以便得到的除数是 n 以下最接近的 2 次幂。我也试过这个:
def justify(n):
return n / int( '1'.ljust( len( bin(n) ) - 2, '0' ), 2 )
这个只是取二进制表示的长度并以此为基础补零。当然,这只适用于整数。我想知道是否有任何方法可以通过按位运算来执行此操作。二进制文件似乎很适合 2 操作的强大功能。至少,我希望看到一种用按位替换 2 ** floor( log(n,2) )
的方法。如果能处理浮点数加分,但我知道那更复杂。
仅对于整数,您可以使用以下稍微曲折的方式到达那里:
def justify(n):
return n / 1<<(n.bit_length()-1)
我不知道在没有进行重要测试的情况下它是否更快,但使用 timeit
进行的快速测试表明它比您的第一个代码段快两倍。
但是,将 n
转换为分子中的浮点数(以获得浮点数 return)会将其减慢到与原始速度相同的速度。
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
慢一个数量级
math.frexp(x)
,正如 Mark Dickinson 在问题评论中指出的那样,是要走的路:
def justify(n):
return 2*frexp(n)[0]
它适用于浮点数和整数。
在纯音调理论中,一种音乐理论,音符之间的间隔用有理数表示。以 2:1 比率将频率加倍可将其提高一个八度,而 1:1 比率则没有变化;齐声。因此,如果我有一个大于八度或小于同音(下降)的音程 n,'justify' 就很有用。也就是说,要使 1 ≤ n ≤ 2。我在 Python 中使用以下函数执行此操作:
def justify(n):
return n / 2 ** floor( log(n,2) )
实际的功能涉及到分数库,但这可以用浮点数和整数来完成工作。对数计算 2 n 的幂次方,然后 floor 将其向下舍入,以便得到的除数是 n 以下最接近的 2 次幂。我也试过这个:
def justify(n):
return n / int( '1'.ljust( len( bin(n) ) - 2, '0' ), 2 )
这个只是取二进制表示的长度并以此为基础补零。当然,这只适用于整数。我想知道是否有任何方法可以通过按位运算来执行此操作。二进制文件似乎很适合 2 操作的强大功能。至少,我希望看到一种用按位替换 2 ** floor( log(n,2) )
的方法。如果能处理浮点数加分,但我知道那更复杂。
仅对于整数,您可以使用以下稍微曲折的方式到达那里:
def justify(n):
return n / 1<<(n.bit_length()-1)
我不知道在没有进行重要测试的情况下它是否更快,但使用 timeit
进行的快速测试表明它比您的第一个代码段快两倍。
但是,将 n
转换为分子中的浮点数(以获得浮点数 return)会将其减慢到与原始速度相同的速度。
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**
方法更好的性能.. 它似乎比
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
math.frexp(x)
,正如 Mark Dickinson 在问题评论中指出的那样,是要走的路:
def justify(n):
return 2*frexp(n)[0]
它适用于浮点数和整数。