在字节数组中计算奇偶校验位(如果有效位数是奇数还是偶数)的最有效方法是什么?我已经迭代了所有的位并总结了有效位,但这纯粹基于较大字节数组/文件所需的迭代次数而非常不切实际。
答案 0 :(得分:1)
为了您的方便(以及我的好奇心),我使用奇偶校验查找表进行了一些时序测试,与目前建议的其他两种方法相比:
Module Module1
Dim rand As New Random
Dim parityLookup(255) As Integer
Sub SetUpParityLookup()
' setBitsCount data from http://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer
Dim setBitsCount = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
}
For i = 0 To 255
parityLookup(i) = setBitsCount(i) And 1
Next
End Sub
' Method using lookup table
Function ParityOfArray(a() As Byte) As Integer
Dim parity As Integer = 0 ' use an Integer because they are faster
For i = 0 To a.Length - 1
parity = parity Xor parityLookup(a(i))
Next
Return parity
End Function
' Method by Alireza
Function ComputeParity(bytes() As Byte) As Byte
Dim parity As Boolean = False
For i As Integer = 0 To bytes.Length - 1
Dim b As Byte = bytes(i)
While b <> 0
parity = Not parity
b = CByte(b And (b - 1))
End While
Next
Return Convert.ToByte(parity)
End Function
' Method by dbasnett
Function CountBits(byteArray As Byte()) As Integer
Dim rv As Integer = 0
For Each b As Byte In byteArray
Dim count As Integer = b
count = ((count >> 1) And &H55) + (count And &H55)
count = ((count >> 2) And &H33) + (count And &H33)
count = ((count >> 4) And &HF) + (count And &HF)
rv += count
Next
Return rv
End Function
Sub FillWithRandomBytes(ByRef a() As Byte)
rand.NextBytes(a)
End Sub
Sub Main()
SetUpParityLookup()
Dim nBytes = 10000
Dim a(nBytes - 1) As Byte
FillWithRandomBytes(a)
Dim p As Integer
Dim sw As New Stopwatch
sw.Start()
p = ParityOfArray(a)
sw.Stop()
Console.WriteLine("ParityOfArray - Parity: {0} Time: {1}", p, sw.ElapsedTicks)
sw.Restart()
p = ComputeParity(a)
sw.Stop()
Console.WriteLine("ComputeParity - Parity: {0} Time: {1}", p, sw.ElapsedTicks)
sw.Restart()
p = CountBits(a)
sw.Stop()
' Note that the value returned from CountBits should be And-ed with 1.
Console.WriteLine("CountBits - Parity: {0} Time: {1}", p And 1, sw.ElapsedTicks)
Console.ReadLine()
End Sub
End Module
典型的输出:
ParityOfArray - Parity: 0 Time: 386
ComputeParity - Parity: 0 Time: 1014
CountBits - Parity: 0 Time: 695
答案 1 :(得分:0)
执行此操作的有效方法是在循环中使用x & (x - 1)
操作,直到x
变为零。这样,您将仅通过设置为1的位数循环。
在VB.NET中用于字节数组:
Function ComputeParity(bytes() As Byte) As Byte
Dim parity As Boolean = False
For i As Integer = 0 To bytes.Length - 1
Dim b As Byte = bytes(i)
While b <> 0
parity = Not parity
b = b And (b - 1)
End While
Next
Return Convert.ToByte(parity)
End Function
答案 2 :(得分:0)
这是一个计数位的函数。
Private Function CountBits(byteArray As Byte()) As Integer
Dim rv As Integer = 0
For x As Integer = 0 To byteArray.Length - 1
Dim b As Byte = byteArray(x)
Dim count As Integer = b
count = ((count >> 1) And &H55) + (count And &H55)
count = ((count >> 2) And &H33) + (count And &H33)
count = ((count >> 4) And &HF) + (count And &HF)
rv += count
Next
Return rv
End Function
注意:这段代码来自我几年前发现的一些尖锐的黑客攻击。我将它转换为VB。