我有一個配置值以二進制數表示,以允許在相同值內的多個選項。將二進制數5轉換爲整數列表(4,1)
E.g. 5的值將是「101」或4和1.
有沒有人知道最好/最快的方式來「輸入」值「5」並獲得{1,4}列表回來?
我有一個配置值以二進制數表示,以允許在相同值內的多個選項。將二進制數5轉換爲整數列表(4,1)
E.g. 5的值將是「101」或4和1.
有沒有人知道最好/最快的方式來「輸入」值「5」並獲得{1,4}列表回來?
如果你想獲得的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
...
所有你必須在這一步之後做 - 過濾出零。
你可能想在'Where()' – aloisdg
@aloisdg是的後面翻轉,我知道這個順序是從1到2^15。我相信這取決於將數字降序排列:) –
一些位轉移和&
後...
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
}
}
簡易方法:
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));
我做這個小樣本。在這裏你從一個整數中得到它的值作爲它的兩個冪的和。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
希望它可以幫助
一個可能更傳統和易於理解的解決方案。在轉換數字成字符串二進制表示,然後在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++;
}
短期分析每個字符提取每個位對應的十進制表示,快速:
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);
}
要顯示二進制表示使用
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
你的意思是{4,1}因爲4 + 1 = 5嗎?所以如果我有12我應該返回{8,4}? 15 = {8,4,2,1} – LuxGiammi
你的意思是一個布爾列表? – aloisdg
爲什麼不是3 + 2? –