![](/img/trans.png)
[英]How to find the position of the only-set-bit in a 64-bit value using bit manipulation efficiently?
[英]find ones position in 64 bit number
我試圖在64位數字中找到兩個1的位置。 在這種情況下,那些位於第0和第63位置。 這里的代碼返回0和32,這只是對齊的一半。 為什么這不起作用?
#include<stdio.h>
void main()
{
unsigned long long number=576460752303423489;
int i;
for (i=0; i<64; i++)
{
if ((number & (1 << i))==1)
{
printf("%d ",i);
}
}
}
線路上有兩個漏洞
if ((number & (1 << i))==1)
哪個應該讀
if (number & (1ull << i))
將1
更改為1ull
意味着左移是在unsigned long long
類型而不是int
,因此位掩碼實際上可以到達位置32到63.將比較刪除為1是因為number & mask
的結果(其中mask
只有一位設置)是mask
或0
,當i為0時mask
僅等於1。
但是,當我進行更改時,我的輸出為0 59
,這仍然不是您所期望的。 剩下的問題是576460752303423489(十進制)= 0800 0000 0000 0001
(十六進制)。 0 59
是該數字的正確輸出。 您想要的號碼是9223372036854775809(十進制)= 8000 0000 0000 0001
(十六進制)。
順便說一句, main
需要返回int
,而不是void
,並且需要顯式return 0;
作為它的最后一個動作(除非你使用返回代碼做一些更復雜的事情)。 是的,C99讓你省略。 無論如何要這樣做。
因為(1 << i)
是您正在編譯和運行的平台上的32位int
值。 這然后得到符號擴展到64位的&
操作與所述number
值,從而導致位31至63被復制成位32。
此外,您正在將&
的結果&
1進行比較,這是不正確的。 如果該位置位則不為0,但不會為1。
將32位int移位32是未定義的。
此外,您的輸入數字不正確。 設置的位位於0和59位(如果您希望從1開始計數,則為1和60)。
修復是使用(1ull << i),或以其他方式右移原始值和&
它為1(而不是左移1)。 當然,如果你用左移1和&
它與原始值,結果將不是1(除了位0),所以你需要比較!= 0
而不是== 1
。
#include<stdio.h>
int main()
{
unsigned long long number = 576460752303423489;
int i;
for (i=0; i<64; i++)
{
if ((number & (1ULL << i))) //here
{
printf("%d ",i);
}
}
}
首先是使用1ULL
來表示unsigned long long
常量。 第二個是在if
語句中,你的意思是不與1
進行比較,這對於最右邊的位只會是真的。
輸出: 0 59
這是正確的,因為576460752303423489
等於0x800000000000001
通過采用將>>
運算符應用於變量而不是文字的方法,首先可以避免這個問題:
if ((variable >> other_variable) & 1)
...
我知道這個問題有一些時間和多個正確的答案,而我應該是一個評論,但它有點太長了。 我建議你在宏中封裝位檢查邏輯,不要直接使用64號,而是計算它。 看一下相當全面的位操作黑客來源。
#include<stdio.h>
#include<limits.h>
#define CHECK_BIT(var,pos) ((var) & (1ULL<<(pos)))
int main(void)
{
unsigned long long number=576460752303423489;
int pos=sizeof(unsigned long long)*CHAR_BIT-1;
while((pos--)>=0) {
if(CHECK_BIT(number,pos))
printf("%d ",pos);
}
return(0);
}
可以使用編譯器工具以最有效的方式執行位分析任務(在許多情況下僅使用單個CPU指令),而不是訴諸位操作。
例如,gcc和clang提供了那些方便的例程:
__builtin_popcountll() - number of bits set in the 64b value
__builtin_clzll() - number of leading zeroes in the 64b value
__builtin_ctzll() - number of trailing zeroes in the 64b value
__builtin_ffsll() - bit index of least significant set bit in the 64b value
其他編譯器具有類似的機制。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.