math - 检查一个数是否可​​以表示为 2 的 x 次幂之和

标签 math binary bit-manipulation

是否有一些小技巧可以检查一个数字是否可以表示为 2 的 x 次幂之和?

示例:对于 x=3 n=21,数字为 16、4 和 1。如果 n=30,则应该为 false,因为不存在 3 的 2 的幂来表示 30。

最佳答案

对于数字 n ...

  • …最小的x是1的个数-n 中的位。这个数字称为 popcount(n)。
    示例:二进制数0b1011至少需要 popcount( 0b1011 )=3 2 的幂才能求和 ( 0b1000 + 0b0010 + 0b0001 )。
  • ...最大 x 为 n。因为1是 2 的幂,您可以添加 1 n次得到n。

现在来了一个难题。如果 x 介于 popcount(n) 和 n 之间怎么办?
事实证明,所有这些 x 都是可能的。求 2 的 x 次方之和……

  • 从最短的总和(n 的二进制表示)开始
  • 如果加数少于 x 个,则将任何大于 1 的加数分成两个加数,将加数的数量增加 1。可以一直这样做,直到到达 x=n。

示例:Can 11= 0b1011可以表示为 x=7 的 2 的幂之和?

是的,因为 popcount(n)=3 <= x=7 <= n=11。

要计算 x=7 的 2 的幂,我们使用
11 = 0b1011 =0b1000 + 0b10 + 0b1 |只有 3 个加数,所以拆分一个
= ( 0b100 + 0b100 )+ 0b10 + 0b1 |只有 4 个加数,所以再拆分一个
= (( 0b10 + 0b10 )+ 0b100 )+ 0b10 + 0b1 |只有 5 个加数,所以再拆分一个
= ((( 0b1 + 0b1 )+ 0b10 )+ 0b100 )+ 0b10 + 0b1 |只有 6 个加数,所以再拆分一个
= ((( 0b1 + 0b1 )+( 0b1 + 0b1 ))+ 0b100 )+ 0b10 + 0b1 | 7 个加数,完成

实现

要实现检查»n可以表示为二的x次幂之和吗?<使用

isSumOfXPowersOfTwo(n, x) {
   return x<=n && x>=popcount(n).
}

为了有效地执行 popcount请参阅this question 。有些处理器甚至有相关指令。

关于math - 检查一个数是否可​​以表示为 2 的 x 次幂之和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68228471/

相关文章:

c - 如何将具有右位移位的数字除以非 2 的幂

xslt - 在 XSLT 中计算

algorithm - 如果 p 是素数,如何使用快速算法检查 ap + b 是否是素数?

Java 二进制到十进制格式/如何分配正确的输入?

c++ - 从缓冲区输入的位

java - 使用 UDP 数据包以位特定顺序发送电话号码 Java

algorithm - 为给定的分母范围找到最接近的 Pi 近似值

javascript - 用颜色表示数字,差异不足以用于基于百分比的 RGB

c++ - 用于计算位或找到最右边|最左边的位的高效按位运算

c++ - 我怎样才能在内存中恰好有 2 位?