C# 位数组相等
在我的应用程序中,我需要的不仅仅是C# 位数组相等,c#,.net,equals,bitarray,C#,.net,Equals,Bitarray,在我的应用程序中,我需要的不仅仅是System.Collections.BitArray类。具体来说,我需要位数组: 不变 使用值语义实现相等 我创建了自己的struct,主要复制了BitArray实现的内部结构。(谢谢 我不是每天都处理逐位运算,所以我对我的平等实现没有最高程度的信心。(它通过了我正在进行的单元测试,但我可能遗漏了一些边缘案例。)我提出的解决方案如下所示。我希望其他人的反馈和回答能更正确、更有效 与CLR位数组一样,长度字段指的是结构中的位数,数组字段(或数组属性)指的是表
System.Collections.BitArray
类。具体来说,我需要位数组:
- 不变
- 使用值语义实现相等
struct
,主要复制了BitArray
实现的内部结构。(谢谢
我不是每天都处理逐位运算,所以我对我的平等实现没有最高程度的信心。(它通过了我正在进行的单元测试,但我可能遗漏了一些边缘案例。)我提出的解决方案如下所示。我希望其他人的反馈和回答能更正确、更有效
与CLR位数组
一样,长度
字段指的是结构中的位数,数组
字段(或数组
属性)指的是表示位的32位整数数组
[澄清]我选择在构造函数和其他方法中采用简单的方法,这样我就不能依赖不必要的位为零。比如说,
通过对整数数组元素进行位求反(Not()
)来实现~
- 可以使用一个构造函数,该构造函数采用长度和布尔值来初始化所有位。如果初始化值为true,我将int数组的所有元素设置为-1(以2的补码表示,由所有1表示)
- 等等
public bool Equals(ImmutableBitArray other)
{
if (this.length != other.length)
{
return false;
}
for (int i = 0; i < this.Array.Length; i++)
{
if (this.Array[i] != other.Array[i])
{
// This does not necessarily mean that the relevant bits of the integer arrays are different.
// Is this before the last element in the integer arrays?
if (i < this.Array.Length - 1)
{
// If so, then the objects are not equal.
return false;
}
// If this is the last element in the array we only need to be concerned about the bits
// up to the length of the bit array.
int shift = 0x20 - (this.length % 0x20);
if (this.Array[i] << shift != other.Array[i] << shift)
{
return false;
}
}
}
return true;
}
public bool Equals(不可变位数组其他)
{
if(this.length!=其他.length)
{
返回false;
}
for(int i=0;i 如果(this.Array[i]如果在ImmutableBitArray
的构造函数中,最后一个元素上未使用的“填充位”被强制归零,则无需跳转到环中,只检查最后一个元素中的有效位,因为在相同的实例中填充将相同
这将很好地简化Equals()
和GetHashCode()
方法:
public bool Equals(ImmutableBitArray other)
{
if (this.length != other.length)
{
return false;
}
for (int i = 0; i < this.Array.Length; i++)
{
if (this.Array[i] != other.Array[i])
{
// since padding bits are forced to zero in the constructor,
// we can test those for equality just as well and the valid
// bits
return false;
}
}
return true;
}
public override int GetHashCode()
{
int hc = this.length;
for (int i = 0; i < this.Array.Length; i++)
{
// since padding bits are forced to zero in the constructor,
// we can mix those into the hashcode no problem
hc ^= this.Array[i];
}
return hc;
}
public bool Equals(不可变位数组其他)
{
if(this.length!=其他.length)
{
返回false;
}
for(int i=0;i
更新:我下面的原始分析不正确
不幸的是,经过几个小时的搜索和研究,我对的行为不正确,我终于得到了我的答案并想与大家分享。我没有回顾性能,因为我只关心可读性
if (input1.length != input2.length)
{
return false;
}
var result = new BitArray(input1);
result = result.Xor(input2);
if (result.Cast<bool>().Contains(true))
return false;
return true;
if(input1.length!=input2.length)
{
返回false;
}
var结果=新的位数组(input1);
结果=结果.Xor(输入2);
if(result.Cast()包含(true))
返回false;
返回true;
数组成员的类型是什么?不必特别处理最后一个字节,高位将为零。@nobugz:我创建实例的方式并不总是正确的。(请参阅下面我对Michael Burr的评论;另请参阅ctor(int,bool)
中的位数组
;我使用-1做同样的事情。)但这可能是更简单的方法。我认为当位长度是32的倍数时,这里实际上存在一个微妙的错误。有关详细信息,请参阅我的第二个答案(不是对第一个答案的编辑):+1非常好的想法。实际上,我是沿着这条路开始的。但它也使其他一些函数复杂化。例如,执行not()的最简单方法
就是做result.Array[i]=~this.Array[i]
对于int数组中的每个元素,这将在零部分中留下1。我必须在某个地方处理多余的元素,在我的情况下,在比较点进行处理是最简单的。是的-我想你必须在某个地方付费。+1非常好!我想知道为什么我在这个场景中的单元测试通过并发现了这一点(至少在C中),n在我的例子中,我允许使用零长度的位数组,因此一些风格上的建议将失败。但很明显,我在我的问题中没有提到这一点,所以你没有办法知道。谢谢你的建议!@Dave:我对我认为的bug的描述是不正确的-C定义了左移位运算符来完成代码所需的操作。我已经在答案的开头添加了一个勘误表…我还考虑了xor运算符。但只有当我们能够以某种方式获得底层字节并与0进行比较,而不是迭代每个位时,这才有用。
(this.Array[i] << shift)
(this.Array[i] << (shift & 0x1f))
int shift = 0x20 - (this.length % 0x20);
if (this.Array[i] << shift != other.Array[i] << shift)
public bool Equals(ImmutableBitArray other)
{
if (this.length != other.length)
{
return false;
}
int finalIndex = this.Array.Length - 1;
for (int i = 0; i < finalIndex; i++)
{
if (this.Array[i] != other.Array[i])
{
return false;
}
}
// check the last array element, making sure to ignore padding bits
int shift = 32 - (this.length % 32);
if (shift == 32) {
// the last array element has no padding bits - don't shift
shift = 0;
}
if (this.Array[finalIndex] << shift != other.Array[finalIndex] << shift)
{
return false;
}
return true;
}
if (input1.length != input2.length)
{
return false;
}
var result = new BitArray(input1);
result = result.Xor(input2);
if (result.Cast<bool>().Contains(true))
return false;
return true;