2017-06-07 44 views
-1

我有一個配置值以二進制數表示,以允許在相同值內的多個選項。將二進制數5轉換爲整數列表(4,1)

E.g. 5的值將是「101」或4和1.

有沒有人知道最好/最快的方式來「輸入」值「5」並獲得{1,4}列表回來?

+1

你的意思是{4,1}因爲4 + 1 = 5嗎?所以如果我有12我應該返回{8,4}? 15 = {8,4,2,1} – LuxGiammi

+0

你的意思是一個布爾列表? – aloisdg

+1

爲什麼不是3 + 2? –

回答

3

如果你想獲得的2,它的值由權力:

int value = 5; 
var addendums = Enumerable.Range(0, sizeof(int) * 8 - 1) 
          .Select(i => (1 << i) & value) 
          .Where(x => x != 0) 
          .ToList(); 

結果:

[ 1, 4 ] 

請注意,如果你想擁有降序增編,就可以申請Reverse()過濾順序後。


TL; DR第一步生成對應於比特位置中的整數值0, 1, 2, ..., 31整數值。最大索引是Int32值中的位數 - 1(因爲我們需要位的索引)。

下一步選擇位與操作的結果的1轉移到相應的索引(與2的冪)與值本身(在此僅示出了前4位):

i 1<<i  value   (1<<i) & value 
    Binary Binary  Binary  Decimal 
0 0001  0101   0001   1 
1 0010  0101   0000   0 
2 0100  0101   0100   4 
3 1000  0101   0000   0 
... 

所有你必須在這一步之後做 - 過濾出零。

+1

你可能想在'Where()' – aloisdg

+0

@aloisdg是的後面翻轉,我知道這個順序是從1到2^15。我相信這取決於將數字降序排列:) –

1

一些位轉移和&後...

int n = 5+32; 
var lst = new List<int>(); 

int i = 1; 
while (n > 0) 
{ 
    if ((n & i) == i) 
    { 
     lst.Add(i); 
     n &= ~i; 
    } 

    i <<= 1; // equivalent to i *= 2 
} 

多一點深奧,使用XOR的(^):

if (n != 0) 
{ 
    while (true) 
    { 
     if ((n & i) != 0) 
     { 
      lst.Add(i); 
      n ^= i; 

      if (n == 0) 
      { 
       break; 
      } 
     } 

     i <<= 1; // equivalent to i *= 2 
    } 
} 
0

簡易方法:

int originalInput = 42; 
int input = originalInput; 

// Generate binary numbers 
var binaryNumbers = Enumerable.Range(0, 31).Select(n => (int)Math.Pow(2, n)).ToArray(); 

// Largest first 
Array.Reverse(binaryNumbers); 

var result = new List<int>(); 

foreach (var bin in binaryNumbers) 
{ 
    if (input >= bin) 
    { 
     result.Add(bin); 
     input -= bin; 
    } 
} 

Console.WriteLine($"{originalInput} decomposed: " + string.Join(" ", result)); 

生成一個範圍從2^31(1073741824)t o 2^0(1),然後檢查輸入是否等於或大於這些數字,如果是,則將該數字添加到結果列表並從輸入中減去它。

現在全部寫出來了,看看謝爾蓋的回答如何大大減少了一些Linq和移位幻術所需的代碼。

的混合解決方案,靈感來自兩個答案結合:

var input = 42; 

var output = Enumerable.Range(0, 31) 
         .Select(n => (int)Math.Pow(2, n)) 
         .Where(p => (p & input) > 0); 

Console.WriteLine($"{input} decomposed: " + string.Join(" ", output)); 
0

我做這個小樣本。在這裏你從一個整數中得到它的值作爲它的兩個冪的和。Thosw權力應該是你的輸入選項

class Program 
    { 
     static void Main(string[] args) 
     { 
      var input = 5; 
      var options = new List<uint>(); 

      for (uint currentPow = 1; currentPow != 0; currentPow <<= 1) 
       if ((currentPow & input) != 0) 
        options.Add(currentPow); 

      foreach (var option in options) 
       Console.WriteLine(option); 

      Console.ReadLine(); 
     } 
    } 

,輸出爲:1 4

編輯>>>其實這樣做一樣@Sergey Berezovskiy的答案,但沒有LINQ

希望它可以幫助

0

一個可能更傳統和易於理解的解決方案。在轉換數字成字符串二進制表示,然後在1

int number = 5; 
string binaryRep = Convert.ToString(number, 2); 
List<int> myList = new List<int>(); 
int pow = 0; 

for(int i = binaryRep.Count() - 1; i >= 0; i--) 
{ 
    if(binaryRep[i] == '1') 
    { 
     myList.Add((int)Math.Pow(2, pow)); 
    } 

    pow++; 
} 
0

短期分析每個字符提取每個位對應的十進制表示,快速:

int input = 5; 
var list = new List<int>(); 

for (int i = 1, j = input; i <= j; i *= 2, input >>= 1){ 
    if ((input & 1) == 1) 
     list.Add(i); 
} 
0

要顯示二進制表示使用

int value = 7; 
var binary = Convert.ToString(value, 2); 

要查看二進制數:

private int[] ToBinaryNumbers(int value) 
    { 
     var binary = Convert.ToString(value, 2).Reverse(); 
     int ix = 0; 
     return binary.Select(x => { var res = x == '1' ? (int?)Math.Pow(2, ix) : (int?)null; ix++; return res; }).Where(x => x.HasValue).Select(x => x.Value).ToArray(); 
    } 

這會給你1,2,4爲7或1,8爲9