如何简化和优化此校验和代码?
好的,这段代码可以工作,但我认为中间有一些必要的步骤才能达到结果。关于如何使其更紧有什么想法吗?
Public Function CalCheckSum(ByVal ByteList As List(Of Byte)) As List(Of Byte)
Dim total As Integer = 0
For Each b As Byte In ByteList
total = total + b
Next
Dim modedVal As Integer = 0
modedVal = total Mod &H100
Dim negatedValue As Integer = 0
negatedValue = &H100 - modedVal
Dim charList As List(Of Char) = Hex(negatedValue).ToCharArray.ToList
Dim returnList As New List(Of Byte)
For Each ch As Char In charList
returnList.Add(Asc(ch))
Next
Return returnList
End Function
顺便说一句,这就是我用来测试它的内容:
Dim blist As New List(Of Byte)
blist.Add(&H52)
blist.Add(&H34)
blist.Add(&H35)
blist.Add(&H31)
blist.Add(&H32)
blist.Add(&H33)
blist.Add(&H34)
blist.Add(&H30)
blist.Add(&H30)
blist.Add(&H30)
blist.Add(&H30)
blist.Add(&H46)
blist.Add(&H46)
blist.Add(&H46)
blist.Add(&H46)
blist.Add(&H42)
blist.Add(&H4B)
blist.Add(&H9)
blist.Add(&H44)
Dim b As List(Of Byte) = CalCheckSum(blist)
b
的正确值是:
b(0)
= &H43b(1)
= &H39
Ok this code works but I think it has some necessary steps in the middle to get to the outcome. Any thoughts on how to make it tighter?
Public Function CalCheckSum(ByVal ByteList As List(Of Byte)) As List(Of Byte)
Dim total As Integer = 0
For Each b As Byte In ByteList
total = total + b
Next
Dim modedVal As Integer = 0
modedVal = total Mod &H100
Dim negatedValue As Integer = 0
negatedValue = &H100 - modedVal
Dim charList As List(Of Char) = Hex(negatedValue).ToCharArray.ToList
Dim returnList As New List(Of Byte)
For Each ch As Char In charList
returnList.Add(Asc(ch))
Next
Return returnList
End Function
BTW This is what I'm using to test it:
Dim blist As New List(Of Byte)
blist.Add(&H52)
blist.Add(&H34)
blist.Add(&H35)
blist.Add(&H31)
blist.Add(&H32)
blist.Add(&H33)
blist.Add(&H34)
blist.Add(&H30)
blist.Add(&H30)
blist.Add(&H30)
blist.Add(&H30)
blist.Add(&H46)
blist.Add(&H46)
blist.Add(&H46)
blist.Add(&H46)
blist.Add(&H42)
blist.Add(&H4B)
blist.Add(&H9)
blist.Add(&H44)
Dim b As List(Of Byte) = CalCheckSum(blist)
The correct values for b
are:
b(0)
= &H43b(1)
= &H39
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
老实说,我不确定您为什么要浪费时间来优化它。在循环中调用该函数超过 100,000 次需要不到 20 毫秒。即使这是应用程序中的“热点”之一(因为您说它与嵌入式硬件设备通信),您也不太可能通过优化现有代码看到任何明显的速度提升。
但只是为了好玩,我决定看看我是否不能稍微优化一下...这是我想到的:
删除多余的
List(Of Char)
创建。您已经使用ToCharArray
方法将值转换为数组。为什么要花大力气调用ToList
来遍历它呢?您也可以迭代数组。这将时间缩短至大约 8 秒,以最小的努力实现了相当大的加速。您还可以将新
List(Of Byte)
的大致大小作为参数传递给构造函数。您已经从charArray
的大小中知道了这一点,因为您只是将每个元素添加回去。当您只处理两个项目时,这没有任何区别,如您提供的示例,但对于大量元素来说,它可以稍微提高效率,因为List
不必在循环期间的任何时候动态调整大小。Asc
、AscW
和Convert.ToInt32
之间完全没有区别。我明确地测量了它们中的每一个,只是为了看看。我的直觉是将其更改为AscW
,但显然这并不重要。许多人会对 VB 特定惯用语的使用嗤之以鼻,并推荐他们认为 .NET Framework 提供的更通用的方法。事实证明,由于所有特定于 VB 的代码都是用与替代代码相同的托管代码编写的,因此您使用的只是一个简单的偏好问题。否则,用简单数组替换
List(Of T)
也不会产生任何明显的差异。由于List
更容易在函数外部使用,因此您不妨将其保留为返回类型。所以我的最终代码看起来像这样:
即使在循环中运行 999,000 次,我仍然将其计时在 62 到 64 毫秒之间。
您还可以使用LINQ。这不是我真正的领域,我怀疑您是否会看到任何可测量的速度增加(它仍然需要在幕后进行相同数量的循环和迭代)。它提供的最大好处是您的代码更简单并且看起来更干净。我很惊讶有人还没有发布这个解决方案。
编辑:顺便说一句,你的原始代码没有为我编译。我必须添加 CByte 运算符来将从
Asc
运算符返回的Integer
值转换为Byte
类型。这告诉我您没有使用 Option Strict 进行编程开。 但您应该这样做。您必须在项目属性中显式设置该选项,但强类型的好处远远超过了检查和修复某些现有代码的成本。您甚至可能会注意到性能有所提高,特别是如果您无意中使用了大量后期绑定。I'm honestly not sure why you'd waste the time it takes to optimize this. Calling that function over 100,000 times in a loop takes less than 20 milliseconds. Even if this is one of the "hot points" in your application (since you say it communicates with an embedded hardware device), it's unlikely that you'll see any appreciable speed increase by optimizing the code that you have.
But just for fun, I decided to see if I couldn't optimize things a little anyway... Here's what I came up with:
Remove the redundant
List(Of Char)
creation. You're already converting the values to an array with theToCharArray
method. Why go through the expense of callingToList
on that, just to iterate through it? You can iterate just as well through an array. This shaves the time down to around 8 seconds, a pretty massive speed-up for minimal effort.You can also pass in the approximate size of your new
List(Of Byte)
as an argument to the constructor. You already know this from the size of yourcharArray
, since you're just adding each of those elements back in. This doesn't make any difference when you're only working with two items, as in the example you provided, but it could make things slightly more efficient for substantially larger numbers of elements because theList
wouldn't have to be dynamically resized at any point during the loop.There's absolutely no difference between
Asc
,AscW
, andConvert.ToInt32
. I measured each of them explicitly just to see. My gut instinct was to change that toAscW
, but apparently it doesn't matter. Lots of people will turn their nose up at the use of VB-specific idioms, and recommend what they consider more universal methods provided by the .NET Framework. It turns out that since all the VB-specific code is written in the same managed code as the alternatives, it's a simple matter of preference which you use.Otherwise replacing
List(Of T)
with simple arrays doesn't make any appreciable difference, either. Since aList
is easier to work with outside of the function, you might as well keep it as the returned type.So my final code looks something like this:
Even running this 999,000 times in a loop, I consistently clock it somewhere between 62 and 64 ms.
You could also use LINQ. It's not really my area, and I doubt you'll see any measurable speed increases (it still has to do the same amount of looping and iterating under the covers). The big benefit it provides is that your code is simpler and looks cleaner. I'm surprised someone hasn't already posted this solution.
EDIT: As an aside, your original code didn't compile for me. I had to add in the
CByte
operator to convert theInteger
value returned from theAsc
operator into aByte
type. That tells me that you're not programming with Option Strict On. But you should be. You have to explicitly set the option in your project's properties, but the benefits of strong typing far outweigh the cost of going through and fixing some of your existing code. You might even notice a performance increase, especially if you've been using a lot of late binding inadvertently.