Нахождение двоичной композиции двоичного числа - PullRequest
0 голосов
/ 18 июня 2020

Совершенно новый для C#, так что это может быть глупый вопрос.

Я работаю со многими UInt64. Они выражаются как шестнадцатеричные, верно? Если мы посмотрим на его двоичное представление, можем ли мы вернуть такой массив, к которому, если мы применим операцию 'или', мы вернемся к исходному UInt64?

Например, скажем

x = 1011

Тогда я ищу эффективный способ прийти к

f(x) = {1000, 0010, 0001}

Где эти числа находятся в шестнадцатеричном, а не двоичном формате. Извините, я тоже новичок в hex.

У меня уже есть метод, но он кажется неэффективным. Сначала я конвертирую в двоичную строку и l oop поверх этой строки, чтобы найти каждую «1». Затем я добавляю соответствующее двоичное число в массив.

Есть мысли?

Вот лучший пример. У меня есть шестнадцатеричное число x в виде

UInt64 x = 0x00000000000000FF

Где двоичное представление x

0000000000000000000000000000000000000000000000000000000011111111

I wi sh, чтобы найти массив, состоящий из шестнадцатеричных чисел (UInt64 ??), так что операция or, примененная ко всем членам этого массива, снова приведет к x. Например,

f(x) = {0x0000000000000080, // 00000....10000000
        0x0000000000000040, // 00000....01000000
        0x0000000000000020, // 00000....00100000
        0x0000000000000010, // 00000....00010000
        0x0000000000000008, // 00000....00001000
        0x0000000000000004, // 00000....00000100
        0x0000000000000002, // 00000....00000010
        0x0000000000000001  // 00000....00000001
}

Думаю, вопрос сводится к поиску эффективного способа найти индекс «1» в двоичном расширении ...

public static UInt64[] findOccupiedSquares(UInt64 pieces){
    UInt64[] toReturn = new UInt64[BitOperations.PopCount(pieces)];
    if (BitOperations.PopCount(pieces) == 1){
        toReturn[0] = pieces;
    }
    else{
        int i = 0;
        int index = 0;
        while (pieces != 0){
            i += 1;
            pieces = pieces >> 1;
            if (BitOperations.TrailingZeroCount(pieces) == 0){ // One
                int rank = (int)(i / 8);
                int file = i - (rank * 8);
                toReturn[index] = LUTable.MaskRank[rank] & LUTable.MaskFile[file];
                index += 1;
            }
        }
    }
    return toReturn;
}

1 Ответ

0 голосов
/ 19 июня 2020

Ваш вопрос все еще смущает меня, поскольку вы, кажется, смешиваете концепции чисел и представления чисел. т.е. есть целое число, а затем есть шестнадцатеричное представление этого целого числа.

Вы можете очень просто разбить любое целое число на его компоненты с основанием 2.

ulong input = 16094009876; // example input
ulong x = 1;
var bits = new List<ulong>();
do
{
    if ((input & x) == x)
    {
        bits.Add(x);
    }
    x <<= 1;
} while (x != 0);

bits теперь список целых чисел, каждое из которых представляет один из двоичных 1 битов входных данных. Это можно проверить, добавив (или сложив ИЛИ - то же самое) все значения. Итак, это выражение истинно:

bits.Aggregate((a, b) => a | b) == input

Если вам нужны шестнадцатеричные представления этих целых чисел в списке, вы можете просто использовать ToString():

var hexBits = bits.Select(b => b.ToString("X16"));

Если вам нужны двоичные представления целых чисел, вы можете использовать Convert:

var binaryBits = bits.Select(b => Convert.ToString((long)b, 2).PadLeft(64, '0'));
...