在 C++ 中处理来自无符号长整型的按位隔离“1s”的方法,在 C# 中有效,但在 C++ 中会产生奇怪的结果

Method to work with bitwise isolated "1s" from an unsigned long long in C++, works in C# but creates strange results in C++

提问人:Paul 提问时间:7/15/2023 最后编辑:Paul 更新时间:7/15/2023 访问量:65

问:

我正在将我的国际象棋引擎从 C# 转移到 C++ 以获得更高的性能。我为每个棋子使用位板(无符号长长),代表它们所在的位置。因此,当按位查看这些无符号长多头之一时,每个多头代表一个棋子,每个零代表一个空方块。

我首先将表示一个片段的无符号长长数组条目发送到另一个无符号长长数组: 无符号长整整 r = 仓位[2]

当我计算 r 中的“1”时,我的方法返回 2,这意味着有两个主教,这是真的。

while r != 0
{

// I have been using a method which counts the Trailing zeros, p locates where the first "1"     lies:

unsigned long long i = r;
unsigned long long y;
            unsigned long long n = 63;
            y = i << 32; if (y != 0) { n = n - 32; i = y; }
            y = i << 16; if (y != 0) { n = n - 16; i = y; }
            y = i << 8; if (y != 0) { n = n - 8; i = y; }
            y = i << 4; if (y != 0) { n = n - 4; i = y; }
            y = i << 2; if (y != 0) { n = n - 2; i = y; }
            int p = n - ((i << 1) >> 63);

/*The method works and for example returns 58 for the bishops, meaning the first bishop is        situated on square 59. Then I'm doing stuff with this position, to estimate the possible moves of  that piece, but that doesn't matter here.
Next, and that is where the problem occurs, I take away the first '1' from r:
*/

r -= (1UL << p)
}

当我现在计算 r 中的“1”时,我的方法返回 33,而它应该返回 1,因为我减去了两个主教中的一个。 最奇怪的是,当我在 C# 中使用相同的代码时(略有变化,无符号 long long 是 ulong 等),该方法有效。

我尝试对 p 使用不同的数据类型或删除“(1UL << p)”中的“UL”。但是我想不出代码有什么问题。这似乎是一个非常简单的愚蠢错误。

C# C++ 国际象棋 无符号

评论

0赞 Garr Godfrey 7/15/2023
我不知道为什么这被否决了。不过,有一种更好的位计数算法。
0赞 Eljay 7/15/2023
为什么而不是?r -= (1UL << p)r -= (1ULL << p)
1赞 Garr Godfrey 7/15/2023
但 1UL 只有 32 位。需要 1ULL
1赞 Pete Becker 7/15/2023
@GarrGodfrey -- 至少为 32 位。它可以更大。但是,当然,这仍然是正确的事情。1UL1ULL
2赞 Pete Becker 7/15/2023
如果有 C++ 20 或更高版本,请使用 std::p opcount

答: 暂无答案