【问题标题】:Finding the binary composition of a binary number查找二进制数的二进制组合
【发布时间】:2020-06-18 00:59:53
【问题描述】:

对 C# 非常陌生,所以这可能是一个愚蠢的问题。

我正在使用很多 UInt64。这些都表示为十六进制对吗?如果我们查看它的二进制表示,我们是否可以返回这样一个数组,如果我们对其应用“或”操作,我们将返回原始 UInt64?

比如说

x = 1011

然后,我正在寻找一种有效的方法来到达,

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

这些数字是十六进制的,而不是二进制的。对不起,我也是十六进制的新手。

我已经有方法了,但是感觉效率低下。我首先转换为二进制字符串,然后遍历该字符串以找到每个“1”。然后我将相应的二进制数添加到数组中。

有什么想法吗?

这是一个更好的例子。我有一个十六进制数 x,格式为,

UInt64 x = 0x00000000000000FF

x 的二进制表示在哪里

0000000000000000000000000000000000000000000000000000000011111111

我希望找到一个由十六进制数字 (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;
}

【问题讨论】:

  • 嗨 Kieran,这个问题有点令人困惑。您是否想要一个表示数字的以 2 为底的分量的字符串数组(例如 0001、0100)?还是您只想要一个数字数组来表示数字的每个以 2 为底的分量(例如 1、4)?
  • 嗨@IgbyLargeman。感谢您的答复。我已经编辑了我原来的问题,我希望它更清楚。归根结底,我仍然需要将结果作为 UInt64 的数组。
  • 您好 Kieran,您的编辑有帮助,但我仍然不确定您是否需要整数数组或字符串数​​组。我问的原因是你不能有一个“十六进制数字数组”。您当然可以有一个字符串数组来表示十六进制格式的数字,但是如果您将实际的 numbers 放入数组中,则没有表示形式;它们只是数字。如果您将它们存储为“十六进制格式”,那么您将它们存储为字符串,并且您必须将它们转换回整数,然后再将它们重新组合在一起。
  • @IgbyLargeman 感谢您对这个问题的持续关注。我希望我的最新编辑会更有帮助。这是我对这个问题的最新尝试。正如我所说,我是 C# 的新手,但我相信你可以弄清楚它是如何工作的。记住,我正在开发一个国际象棋引擎,所以名字是有原因的!

标签: c#-4.0 binary uint64 bitboard


【解决方案1】:

您的问题仍然让我感到困惑,因为您似乎混淆了数字和数字表示的概念。即有一个整数,然后有该整数的十六进制表示。

您可以非常简单地将任何整数分解为其以 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 位。这可以通过添加(或 ORing - 相同的东西)所有值来验证。所以这个表达式是真的:

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'));

【讨论】:

  • 感谢您的回答。我认为这会有所帮助!您是否会碰巧知道我可以根据我的解决方案对此进行测试?对于这个问题的混淆,我很抱歉。我们用一个 64 位的二进制数来表示一个棋盘状态,例如,白棋的棋盘可以是 000....1111111100000000。所以每个'1'都是一个棋子。我想要一个 64 位二进制数中每个棋子的位置。对我来说更具挑战性的是,大多数人不是以二进制格式表示,而是以十六进制格式表示这些数字。
  • 仍然不确定你到底需要什么,但我会补充一点关于获取二进制格式的信息。我已经向您展示了如何获取十六进制格式。
猜你喜欢
  • 2014-09-09
  • 1970-01-01
  • 1970-01-01
  • 2019-11-25
  • 1970-01-01
  • 2015-05-01
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多