array split

介绍 (Introduction)

关于最近的一个问题,我提供了一个简单的函数来格式化带后缀的数字,以表示其大小(MB,GB,TB等)。 虽然功能很简单,但我想知道是否提供了最有效的代码。 本文比较了Array()和Split()函数的性能。

()

The Problem

The question (

问题

问题( http:Q_28494315.html) stated a need to add the scale suffix to a number.  Excel did not provide the ability to format cell values this way and conditional formatting does not affect the cell's value.  The cell still contains a numeric value, while Excel displays the formatted value. http:Q_28494315.html )表示需要在数字后加上小数位数后缀。 Excel没有提供以这种方式格式化单元格值的功能,并且条件格式设置不会影响单元格的值。 单元格仍包含数字值,而Excel显示格式化的值。

()

Example:

例:

12345600 = 12.3456 MB

12345600 = 12.3456 MB

1234560000 = 1.23456 GB

1234560000 = 1.23456 GB

()

The Accepted and Alternative Solutions

Since there were only three possible suffixes, the conditional formatting solution was the simplest and the one accepted as the question solution.

公认的和替代的解决方案

由于只有三个可能的后缀,因此条件格式解决方案是最简单的,而一个被接受为问题解决方案。
[>999999999999]0.00,,,,"TB";[>999999999]0.00,,,"GB";0.00,,"MB"
ConditionalFormattingRulesMgr.jpg

()

The User-Defined Function Solutions

Let's start with a routine that uses an Array() function, most closely resembling the question's solution.  If the magnitude of the parameter value is greater than 1000, we use the base1000 log of the number to index into the Array() values.

用户定义的功能解决方案

让我们从使用Array()函数的例程开始,该例程最类似于问题的解决方案。 如果参数值的大小大于1000,则使用数字的base1000对数来索引Array()值。

()

SizeA -- An Array() function

SizeA-Array()函数

Public Function SizeA(ByVal parmValue)
    Static lngPower As Long
    If Abs(parmValue) < 1000 Then
        SizeA = parmValue
    Else
        lngPower = Int(Log(parmValue) / Log(1000))
        SizeA = parmValue / (1000 ^ lngPower) & " " & Array("KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")(lngPower - 1)
    End If
End Function

SizeB-一个Split()函数 (SizeB -- A Split() function)

我们已经用在Split函数中使用的一些字符串常量替换了Array()函数。
Public Function SizeB(ByVal parmValue)
    Static lngPower As Long
    Const strSuffix As String = "KB^MB^GB^TB^PB^EB^ZB^YB"
    Const strDelim As String = "^"
    
    If Abs(parmValue) < 1000 Then
        SizeB = parmValue
    Else
        lngPower = Int(Log(parmValue) / Log(1000))
        SizeB = parmValue / (1000 ^ lngPower) & " " & Split(strSuffix, strDelim)(lngPower - 1)
    End If
End Function

头对头性能测试 (Head-to-head Performance test)

我对这两个例程进行了简单的经过时间测试。 在达到10,000次迭代之前,它们之间没有可测量的差异。 即使在进行10K迭代时,边距在例程的SplitB()版本SizeB()上也相差了.02秒。

()

Tweaking the Performance

I decided to play with these two routines to see if I could improve their performance.  Two questions to be addressed:

调整性能

我决定使用这两个例程,看看是否可以提高它们的性能。 需要解决的两个问题:
  1. How much does the Array() function cost to execute inside the function?

    在函数内部执行Array()函数需要多少费用?
  2. Is the use of constant variable declarations faster than string literals?

    使用常量变量声明是否比字符串文字快?

()

SizeAA -- Passing the Array() value

While this might be considered cheating, its superior performance does support the general rule to minimize the number of operations you perform inside a loop or routine.

SizeAA-传递Array()值

尽管这可能被认为是作弊行为,但其卓越的性能确实支持了通用规则,以最大程度地减少您在循环或例程中执行的操作数量。
Public Function SizeAA(ByVal parmValue, ByVal parmSuffixes)
    Static lngPower As Long
    If Abs(parmValue) < 1000 Then
        SizeAA = parmValue
    Else
        lngPower = Int(Log(parmValue) / Log(1000))
        SizeAA = parmValue / (1000 ^ (lngPower)) & " " & parmSuffixes(lngPower - 1)
    End If
End Function

SizeBB-常量与字符串文字 (SizeBB -- constants vs. string literals)

我的印象是常量的行为类似于静态变量。 但是,我的性能指标并没有反映出const字符串和字符串文字之间的性能差异。
Public Function SizeBB(ByVal parmValue)
    Static lngPower As Long
    
    If Abs(parmValue) < 1000 Then
        SizeBB = parmValue
    Else
        lngPower = Int(Log(parmValue) / Log(1000))
        SizeBB = parmValue / (1000 ^ lngPower) & " " & Split("KB^MB^GB^TB^PB^EB^ZB^YB", "^")(lngPower - 1)
    End If
End Function

SizeBBB-模块级常量 (SizeBBB -- module-level constants)

在此配置中,我消除了const字符串或字符串文字的任何可能开销。
Public Function SizeBBB(ByVal parmValue)
    Static lngPower As Long
    
    If Abs(parmValue) < 1000 Then
        SizeBBB = parmValue
    Else
        lngPower = Int(Log(parmValue) / Log(1000))
        SizeBBB = parmValue / (1000 ^ lngPower) & " " & Split(gstrSuffix, gstrDelim)(lngPower - 1)
    End If
End Function

SizeB2-静态字符串变量 (SizeB2 -- static string variables)

在您编写的每个函数中,这项技术都应包含在其中,这些函数涉及对象的某些初始化或变量值的初始设置,其中变量在例程调用期间不会更改值。 在设计模式世界中,这将是例程或类生命周期中的单例事件。
Public Function SizeB2(ByVal parmValue)
    Static lngPower As Long
    Static strSuffix As String
    Static strDelim As String
    If Len(strSuffix) = 0 Then
        strSuffix = "KB^MB^GB^TB^PB^EB^ZB^YB"
        strDelim = "^"
    End If
    If Abs(parmValue) < 1000 Then
        SizeB2 = parmValue
    Else
        lngPower = Int(Log(parmValue) / Log(1000))
        SizeB2 = parmValue / (1000 ^ lngPower) & " " & Split(strSuffix, strDelim)(lngPower - 1)
    End If
End Function

调整了性能比较-多次运行10k (Tweaked performance comparisons -- multiple 10k runs)

MIN     	MAX     	AVERAGE 	ROUTINE
0.0859375	0.09375 	0.08828125	SizeA
0.0546875	0.0625  	0.06171875	SizeAA
0.0625  	0.0703125	0.06796875	SizeB
0.0625  	0.078125	0.06875 	SizeB2
0.0625  	0.078125	0.0703125	SizeBB
0.0625   	0.078125	0.06953125	SizeBBB

结论 (Conclusions)

  • The Split() function is a better performer than the Array() function.

    Split()函数比Array()函数的性能更好。
  • If you can pass an array into your function, regardless of whether the result of an Array() or Split() function invocation, you will get the best performance.

    如果可以将数组传递到函数中,则无论Array()或Split()函数调用的结果如何,都将获得最佳性能。
  • String literals, global constants, local constants, and static (initialize once) variables perform better than module-level constants.

    字符串文字,全局常量,局部常量和静态(初始化一次)变量的性能要好于模块级常量。

时序码 (The Timing Code)

为了帮助您在自己的运行时环境中评估这些不同的例程,这是我用来计时的代码。
Option Explicit

Const gstrSuffix As String = "KB^MB^GB^TB^PB^EB^ZB^YB"
Const gstrDelim As String = "^"


Public Sub timeit()
    Dim sngStart As Single
    Dim lngLoop As Long
    Dim strResult As String
    Const lngCount As Long = 100000
    Dim vSuffixes As Variant
    vSuffixes = Array("KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
    
    sngStart = Timer
    For lngLoop = 1 To lngCount
        strResult = SizeA(123456 + lngLoop)
    Next
    Debug.Print "SizeA", Timer - sngStart, strResult
    
    sngStart = Timer
    For lngLoop = 1 To lngCount
        strResult = SizeAA(123456 + lngLoop, vSuffixes)
    Next
    Debug.Print "SizeAA", Timer - sngStart, strResult
    
    
    sngStart = Timer
    For lngLoop = 1 To lngCount
        strResult = SizeB(123456 + lngLoop)
    Next
    Debug.Print "SizeB", Timer - sngStart, strResult
    
    sngStart = Timer
    For lngLoop = 1 To lngCount
        strResult = SizeBB(123456 + lngLoop)
    Next
    Debug.Print "SizeBB", Timer - sngStart, strResult
    
    sngStart = Timer
    For lngLoop = 1 To lngCount
        strResult = SizeBBB(123456 + lngLoop)
    Next
    Debug.Print "SizeBBB", Timer - sngStart, strResult
    
    sngStart = Timer
    For lngLoop = 1 To lngCount
        strResult = SizeB2(123456 + lngLoop)
    Next
    Debug.Print "SizeB2", Timer - sngStart, strResult
End Sub
A-14860.bas A-14860.bas

 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

=-=-=-=-=-=-=-=-=-=-=-=-= -=-=-=-=-= -=-=-=-=-= -=-=-=-=-= -=-=-=

If you liked this article and want to see more from this author,  please click here.

如果您喜欢本文,并希望从该作者那里获得更多信息, 请单击此处。

If you found this article helpful, please click the Yes link near the:

如果您认为这篇文章对您有所帮助 ,请单击以下位置附近的“

      Was this article helpful?

本文是否有帮助?

label that is just below and to the right of this text.   Thanks!

此文字下方和右侧的标签。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

=-=-=-=-=-=-=-=-=-=-=-=-=- =-=-=-=-=- =-=-=-=-=- =-=-=-=-=- =-=-=

翻译自: https://www.experts-exchange.com/articles/14860/Array-and-Split-performance-comparison.html

array split

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐