簡體   English   中英

查找任意位數字的二進制表示 position

[英]Finding binary representation of a number at any bit position

在過去的一周里,我一直在努力解決這個問題,似乎我最終無法處理它。 給定一個任意 64 位無符號整數,如果它在任何位 position 處包含二進制模式 31 (0b11111),在任何位設置下,該數字有效,否則無效。

例如:

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000 1 1111有效

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 00 11 111 0 有效

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0 111 11 00 有效

0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 1 000 0000 0000 0000 0000 0000 有效

0000 0000 00 11 111 0 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 00 11 111 0 有效等...

還:

0000 0000 0000 1100 0000 0100 0000 0000 1100 1100 0000 0000 0100 0000 000 1 1111有效

1110 0000 0000 0100 0000 0000 0011 0000 0000 0000 0000 0000 0000 0000 00 11 111 0 有效

0000 0000 1000 0010 0000 0010 0000 0000 0000 0000 0010 0000 0000 0000 0 111 11 00 有效

0000 0010 0000 0110 0000 0000 0000 0000 0000 1111 1 000 0000 0000 0100 0110 0000 有效

0000 0000 00 11 111 0 0000 0000 0011 0000 0000 1000 0000 0000 0000 0000 00 11 111 0 有效等...

但:

0000 0000 0000 1100 0000 0100 0000 0000 1100 1100 0000 0000 0100 0000 0000 1111 無效

1110 0000 0000 0100 0000 0000 0011 0000 0000 0000 0000 0000 0000 0000 0011 1100 無效

0000 0000 1000 0010 0000 0010 0000 0000 0000 0000 0010 0000 0000 0000 0101 1100 無效

0000 0010 0000 0110 0000 0000 0000 0000 0000 1111 0000 0000 0000 0100 0110 0000 無效

0000 0000 0011 1010 0000 0000 0011 0000 0000 1000 0000 0000 0000 0000 0001 1110 無效等...

你有道理...

但這只是問題的前半部分。 第二個是,它需要在沒有循環或分支(已經完成)的情況下實現以提高速度,只使用算術和/或邏輯、位操作類型的代碼進行檢查。

我能得到的最接近的是 Bit Twiddling Hacks “確定一個單詞是否有零字節”( https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord )的修改版本來檢查五個位塊零(否定 11111)。 但它仍然具有僅檢查固定位塊(位 0 到 4、位 5 到 9 等)的能力限制,而不是 position 的任何位(如上面的示例)。

任何幫助將不勝感激,因為我已經筋疲力盡了。

大小

執行

讓我用稍微不同的表述重申你的目標:

我想檢查 integer 是否包含 5 個連續的高位。

從這個公式中,以下解決方案可以解釋自己。 它是用 C++ 編寫的。

bool contains11111(uint64_t i) {
   return i & (i << 1) & (i << 2) & (i << 3) & (i << 4);
}

這種方法也適用於任何其他模式。 例如,如果你想檢查010你會使用~i & (i<<1) & ~(i<<2) 在您的示例中,模式的長度是一個素數,但對於合數,尤其是 2 的冪,您可以進一步優化它。 例如,在搜索 1111 1111 時,您可以使用i&=i<<1; i&=i<<2; i&=i<<4; return i i&=i<<1; i&=i<<2; i&=i<<4; return i i&=i<<1; i&=i<<2; i&=i<<4; return i

測試

為了在您的示例上進行測試,我使用了以下程序。 testcases[]中的文字是通過 bash 命令運行您的示例生成的...

{ echo 'ibase=2'; tr -dc '01\n' < fileWithYourExamples; } |
bc | sed 's/.*/UINT64_C(&),/'

#include <cinttypes>
#include <cstdio>

bool contains11111(uint64_t i) {
  return i & (i << 1) & (i << 2) & (i << 3) & (i << 4);
}

int main() {
  uint64_t testcases[] = {
      // valid
      UINT64_C(31),
      UINT64_C(62),
      UINT64_C(124),
      UINT64_C(260046848),
      UINT64_C(17451448556060734),
      UINT64_C(3382101189607455),
      UINT64_C(16142027170561130558),
      UINT64_C(36593945997738108),
      UINT64_C(145804038196167776),
      UINT64_C(17451654848708670),
      // invalid
      UINT64_C(3382101189607439),
      UINT64_C(16142027170561130556),
      UINT64_C(36593945997738076),
      UINT64_C(145804038187779168),
      UINT64_C(16325754941866014),
  };
  for (uint64_t i : testcases) {
    std::printf("%d <- %016" PRIx64 "\n", contains11111(i), i);
  }
}

這打印

1 <- 000000000000001f
1 <- 000000000000003e
1 <- 000000000000007c
1 <- 000000000f800000
1 <- 003e00000000003e
1 <- 000c0400cc00401f
1 <- e00400300000003e
1 <- 008202000020007c
1 <- 020600000f800460
1 <- 003e00300800003e
0 <- 000c0400cc00400f
0 <- e00400300000003c
0 <- 008202000020005c
0 <- 020600000f000460
0 <- 003a00300800001e

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM