C# 中位操作的按位运算符与 .NET 抽象

问题描述 投票:0回答:4

我正在尝试获得使用 C#.NET 处理位的基本技能。我昨天发布了一个示例,其中包含一个需要位操作的简单问题,这使我发现有两种主要方法 - 使用

bitwise operators
或使用 .NET 抽象,例如
BitArray
(如果有更多构建,请告诉我-用于处理 .NET 中除
BitArray
以外的位的工具以及如何查找更多信息(如果有)?)。

我知道

bitwise operators
工作得更快,但使用
BitArray
对我来说更容易,但我真正努力避免的一件事是学习不好的做法。尽管我个人更喜欢 .NET 抽象,但我想知道在实际程序中我实际上更适合学习和使用哪个。考虑到这一点,我很想认为 .NET 抽象并没有那么糟糕,毕竟必须有理由存在,也许作为初学者,学习抽象并随后通过低级操作提高我的技能会更自然,但这只是随意的想法。

c# .net bit-manipulation
4个回答
4
投票

这实际上取决于你用它做什么。当速度更受关注时,我会说使用按位运算,因为它们的开销要少得多。否则,BitArray 应该没问题。相关的主要开销是函数调用以及对您可以执行的“技巧”的一些限制。

例如,如果您想要在值中设置位 0、3 或 4 时执行某些操作:

if((value & 0b11001)>0) //not sure this is valid syntax, but you get the idea
{
   //do stuff
}

由于整数是本机 CLR 类型,因此几乎直接转换为 3 个本机操作码:

mov
and
cmp

对于 BitArray,我认为最有效的方法是:

if(value[0] || value[3] || value[4])
{
  //...
}

其中(假设不是 JIT),这相当于最多 3 个轻复杂度的函数调用。从 BitArray 的支持整数(我假设)获取位值的最简单方法如下所示:

bool GetBit(int which)
{
  return value & (1 << which)>0;
}

这基本上意味着它相当于慢了大约 2 倍仅一位对于这个超级简单的情况,这意味着慢了大约 6 倍,因为我们正在检查 3 位。

对于 BitArray 来说,副本可能更昂贵,因为它们不是本机 CLR 类型。我怀疑大部分开销都被 JIT 消除了,但仍然需要考虑,特别是在针对紧凑框架时。

基本上,只有当您不需要对 BitArray 进行复杂的按位运算时才使用它们。

注意:您还可以使用在整数和 BitArray 之间进行转换的混合方法,但这也会产生相当大的开销。


3
投票

我想知道在实际程序中我实际上更好地学习和使用哪个。

学习它们。它们并不难理解,您可以想象其中一个比另一个更好的场景。

虽然我同意上面的@Marc Gravell,但如果我需要处理大量的位(并且速度不是太大的问题),我只会考虑使用 BitArray,但如果你最终在这种情况下,无论如何你都可能做错了什么。


3
投票

编程时请始终牢记这一点:

“没有什么问题是通过添加另一层间接层无法解决的,除了有太多间接层的问题”。 - 大卫惠勒(第)

通过使用 BitArray,您可以添加一个间接层,该层抽象了如何管理位以及生成和操作每个位的值的详细信息。这通常是一件好事,值得鼓励;它创建了更干净、更优雅、更易于阅读的代码。

但是,当您需要做一些复杂的事情时会发生什么,而 BitArray 不允许您做(或者很难做)?到那时,你的设计就“过于抽象”了;抽象级别阻止您做您想做的事情,因为它们“简化”了太多。这是一个用更少的抽象进行重构的信号,在这种情况下使用按位运算符需要更多的关注和理解,但基本上会对一组位执行任何可能的操作。

简而言之,使用 BitArray 来解决你的问题,直到使用 BitArray 成为它自己的问题为止。不用担心没有 BitArray 你要做什么;可以担心“是否以及何时”有必要。只是不要忘记如何使用按位运算符,或者它们的存在。


0
投票
将 Marc Gravel 的回复从评论迁移到答案:

[...] 在我能想到的几乎所有常见场景中,操作员方法都是首选。我唯一一次查看 BitArray 是当我需要一组
任意大

的标志时,其中 a: 非常罕见,而 b: 通过简单的字节数组或 int 数组来实现是微不足道的无论如何马克·格拉维尔 2012 年 9 月 13 日 15:41

© www.soinside.com 2019 - 2024. All rights reserved.