2015-05-25 53 views
3

我有一個十進制數,我需要將其轉換爲二進制,然後在二進制表示中找到其位置。如何獲取位的位置

輸入是5,其二進制爲101和輸出應該是

1 
3 

下面是我的代碼只提供了輸出2,而不是我想提供的位置之一是在二進制表示。我怎樣才能從1開始獲取設定位的位置?

public static void main(String args[]) throws Exception { 
    System.out.println(countBits(5)); 
} 

private static int countBits(int number) { 
    boolean flag = false; 

    if (number < 0) { 
     flag = true; 
     number = ~number; 
    } 
    int result = 0; 
    while (number != 0) { 
     result += number & 1; 
     number = number >> 1; 
    } 
    return flag ? (32 - result) : result; 
} 
+0

注意:檢查」數字「是否爲負數的代碼不是必需的。如果你使用'>>>'運算符而不是'>>',那麼零將被移入左邊(而不是1被移位到負數),所以'number'最終將爲0,'result'將會始終是正確的計數。 – ajb

+0

如果您試圖返回1位的位置,那麼使用>>>將是必要的。如果你試圖專門處理負數,你的工作將變得更加複雜。 – ajb

回答

7

你有countBits返回結果,而不是把一個System.out.println裏面的想法該方法通常是最好的方法。如果你希望它返回位位置的列表,模擬將有你的方法返回一個數組或某種名單的,如:

private static List<Integer> bitPositions(int number) { 

正如我在我的評論中提到,你會生活如果您使用>>>並且擺脫特殊代碼來檢查底片,對您自己來說更容易。這樣做,並適應你已經擁有的代碼,讓你像

private static List<Integer> bitPositions(int number) { 
    List<Integer> positions = new ArrayList<>(); 
    int position = 1; 
    while (number != 0) { 
     if (number & 1 != 0) { 
      positions.add(position); 
     } 
     position++; 
     number = number >>> 1; 
    } 
    return positions; 
} 

現在主叫方可以做它想做的打印位置出來。如果您使用System.out.println,則輸出將爲[1, 3]。如果你想在一個單獨的行每個輸出:

for (Integer position : bitPositions(5)) { 
    System.out.println(position); 
} 

在任何情況下,有關如何打印位置(或者你想與他們做任何其他)的決定保持距離,計算位置的邏輯分離,因爲該方法返回整個列表並且沒有自己的println。 (順便說一下,正如亞歷克斯說的那樣,儘管我已經看到硬件手冊稱爲低位位,但將低位位視爲「位0」而不是「位1」是最常見的「位31」和高位位「位0」,稱之爲「位0」的優點是N位的1位表示值爲2 N,讓事情變得簡單,我的代碼示例將其稱爲「位1「;但如果要將其更改爲0,只需更改初始值position。)

+0

感謝您的幫助。你能否解釋爲什麼我們要使用按位運算符,只要我們想將任何十進制數轉換爲二進制數?這有什麼合乎邏輯的原因嗎?其實我很迷惑爲什麼按位運算符會進入畫面。爲什麼我們在這裏特別使用了>>>。 – user1950349

+0

數字**的二進制表示是**位。你要求以二進制表示獲得1的位置;這與詢問1位的位置完全相同。這就是我們使用按位運算符的原因。此外,該方法不是將十進制數轉換爲二進制數。 'number'已經以二進制形式存儲在計算機中;十進制到二進制的轉換髮生在很久以前,當編譯器在主方法中看到數字「5」並將其轉換爲二進制。 – ajb

+0

至於'>>>',我想你明白了爲什麼負數是一個問題,這就是爲什麼你特意處理它們的原因。我猜你不會?當一個數字是負數時,最左邊的位是1.當最左邊的位是1時,當它將位移動時,「>>」操作符會在左邊插入另一個1。如果你正在計算1的數量或尋找1位,這個額外的1會讓你感到困惑。 '>>>'不這樣做。它總是在左側插入一個0。 – ajb

3

你需要跟蹤你在什麼位置,當number & 1結果1,打印出位置。它看起來像這樣:

... 
int position = 1; 
while (number != 0) { 
    if((number & 1)==1) 
     System.out.println(position); 
    result += number & 1; 
    position += 1; 
    number = number >> 1; 
} 
... 
1

有一種解決您的問題的位操作方法。
Integer.toBinaryString(int number)將整數轉換爲由零和1組成的字符串。這是你的情況,方便,因爲你可以改爲有:

public static void main(String args[]) throws Exception { 
    countBits(5); 
} 

public static void countBits(int x) { 
    String binaryStr = Integer.toBinaryString(x); 
    int length = binaryStr.length(); 
    for(int i=0; i<length; i++) { 
    if(binaryStr.charAt(i)=='1') 
     System.out.println(length-1); 
    } 
} 

它繞過你可能會試圖做(學習Java中位運算),但使代碼看起來更整潔在我看來。

3

二進制表示法:與現代(非量子)計算機上的任何事物一樣,您的編號已經是內存中的二進制表示,即具有給定大小的位序列。

位操作 您可以使用位移位,位掩碼,「AND」,「OR」,「NOT」和「異或」 bitwise operations操縱他們,讓個人水平位關於它們的信息。

你的榜樣

對於5(101)您的例子數您提到您的預計產出將是1, 3。這有點奇怪,因爲一般來說,人們會從0開始計數,例如, 5爲byte(8比特數):

<-- bit index 
5 00000101 

因此,我期望的輸出爲02因爲在那些比特索引的位被置位(1)。

你的示例實現顯示功能

private static int countBits(int number) 

它的名稱和簽名意味着對任何實施以下行爲的代碼:

  • 它需要一個整數值number並返回一個產值。
  • 它旨在計算輸入number中設置的位數。

I.e.它完全不符合您所描述的預期功能。

溶液

可以使用一個 '位移位'(>>)和AND&)操作的組合解決問題。

int index = 0; // start at bit index 0 

while (inputNumber != 0) { // If the number is 0, no bits are set 

    // check if the bit at the current index 0 is set 
    if ((inputNumber & 1) == 1)   
     System.out.println(index); // it is, print its bit index. 

    // advance to the next bit position to check 
    inputNumber = inputNumber >> 1; // shift all bits one position to the right 
    index = index + 1;    // so we are now looking at the next index. 
} 

如果我們爲您例如輸入數字「5」運行此,我們將看到以下內容:

iteration input index result 
1   5  00000101  0  1 => bit set. 
2   2  00000010  1  0 => bit not set. 
3   1  00000001  2  1 => bit set. 
4   0  00000000  3  Stop, because inputNumber is 0