VBA : 필요한 길이만큼 무작위 숫자 문자열을 출력하는 프로 시저

5547 단어 ExcelExcelVBA

검증 환경


  • CPU: Pentium Dual Core CPU E6300 (2.80GHz)
  • 메모리: 2.00GB
  • OS: Windows 10(32 bit)
  • Office: Excel 2016

  • 주요 기능


  • 임의의 숫자 4자리(지정 자리수 분)를 왼쪽 0 채우는 문자열로서 출력한다
  • 100회 처리의 벤치마크 테스트 결과를 나중에 둡니다. O(n)에서의 가장 빠른 처리를 목표로 했습니다.

  • 만들기 배경


  • 패스워드 관리의 툴로서, 공통 부수 종류와 말미 부숫자 4 자리의 조합으로 생성하고 싶기 때문에
  • 추가 : 범용성을 제공하기 위해 생성 알고리즘을 약간 변경

  • 앞으로 할 수있는 것



  • 긴 문자열에 대응 (현재 4 자리까지, 4 자리 이상은 루프시켜 잘라내기) (완료)
  • → 알고리즘을 대폭 개선해, 처리 속도가 약 50배~5배로 축소. 그러나 문자열 길이에 따라 O(n).
  • → 단, 1문자당 증가율이 많아도 10% 정도로, 1000문자로 추정 약 20(s).
  • 16 진수 대응
  • 영숫자 대응(대문자만→소문자 포함하는 것으로 확장)

  • 메인 소스



    GetRandomDigitsUtil.bas
    Public Function GetRandom4Digit(Optional ByVal digit As Integer = 4) As String
        Dim longVal As Long
        Dim passStr As String
        Dim charVal As String
        Dim charIdx As Long, loopCount As Integer
    
        passStr = ""
        longVal = 0
    
        Do While Len(GetRandom4Digit) < digit
            Randomize
            passStr = CStr(Rnd)
            Randomize
            passStr = passStr & CStr(Rnd)
            passStr = Replace(passStr, "0.", "")
            passStr = Replace(passStr, ".", "")
            passStr = Replace(passStr, "E-", "")
    
            ' 前回のこのプロシージャの前半を流用
            For charIdx = 1 To Len(passStr)
                ' ここでもう4桁分を数値化、For文で1文字(1桁)ずつシフト
                longVal = longVal + CLng(Mid$(passStr, charIdx, 4))
    
                ' 5桁になったら下1桁を結果に追記、右1桁シフトしたものを新たな値とする
                If longVal >= 10000 Then
                    GetRandom4Digit = GetRandom4Digit & Right(CStr(longVal), 1)
                    longVal = CLng(Left(CStr(longVal), Len(CStr(longVal)) - 1))
                End If
                DoEvents
            Next
        Loop
    
        GetRandom4Digit = Left(GetRandom4Digit, digit)
    End Function
    

    벤치마크 테스트


  • 100회분의 처리 시간을 계측(결과의 표는 25문자 이후는 30~10마다)

  • 결과



    (문자열 길이-처리 시간/100회-전회비)




    생성 문자열 길이
    처리 시간(s)
    마지막 비율


    1
    0.320
    -

    2
    0.227
    -29.27%

    3
    0.266
    17.24%

    4
    0.242
    -8.82%

    5
    0.258
    6.45%

    6
    0.313
    21.21%

    7
    0.313
    0.00%

    8
    0.313
    0.00%

    9
    0.344
    10.00%

    10
    0.375
    9.09%

    11
    0.398
    6.25%

    12
    0.414
    3.92%

    13
    0.430
    3.77%

    14
    0.445
    3.64%

    15
    0.453
    1.75%

    16
    0.477
    5.17%

    17
    0.555
    16.39%

    18
    0.531
    -4.23%

    19
    0.547
    2.94%

    20
    0.563
    2.86%

    21
    0.594
    5.56%

    22
    0.609
    2.63%

    23
    0.609
    0.00%

    24
    0.656
    7.69%

    25
    0.672
    2.38%

    30
    0.758
    -

    40
    0.953
    -

    50
    1.125
    -

    60
    1.367
    -

    70
    1.563
    -

    80
    1.750
    -

    90
    2.008
    -

    100
    2.156
    -




    테스트 프로 시저



    TestProc.bas
    'テスト用プロシージャ(100回テスト)
    Private Sub Test(ByVal lenLimit As Integer, ByVal rng As Range)
        Dim startTime As Single, beginProc As Single, endProc As Single, timeProc As Single
        Dim idx As Integer
        Dim offsetLimit As Integer, sampleDigit As Long
        Dim resultStr As String, tempLng As Long
        Dim y0 As Integer, y1 As Single, x0 As Single, x1 As Single
        Dim nextRate As Single
        resultStr = ""
    
        offsetLimit = WorksheetFunction.Min(lenLimit, 0)
    
        startTime = Timer
        beginProc = 0
    
        sampleDigit = 100
    
        For idx = 1 To 100
            resultStr = ""
            beginProc = Timer
    
            Do
                resultStr = resultStr & GetRandom4Digit(lenLimit)
            Loop While Len(resultStr) < lenLimit
    
            resultStr = Left(resultStr, lenLimit)
            Debug.Print "Result: " & resultStr & "(" & Len(resultStr) & ")"
    
            endProc = Timer
            timeProc = endProc - beginProc
        Next
    
        With rng
            .Offset(0, 1).NumberFormat = "0.000"
            .Offset(0, 1).Value = (Timer - startTime)
            If .Row = 2 Then
                .Offset(0, 2).Value = "-"
            Else
                .Offset(0, 2).NumberFormat = "0.00%"
                .Offset(0, 2).Value = (.Offset(0, 1).Value / .Offset(-1, 1).Value) - 1
            End If
        End With
    End Sub
    
    Public Sub TestMain()
        Dim wkSht As Worksheet, rng As Range
        Dim lenCount As Integer
        Call FindSheet("benchmarkTest", wkSht, False, True, ThisWorkbook)
    
        Set rng = wkSht.Cells(1, 1)
        With rng
            .Value = "len"
            .Offset(0, 1).Value = "Time(s)"
            .Offset(0, 2).Value = "rate"
        End With
    
        For lenCount = 1 To 100
            Set rng = wkSht.Cells(lenCount + 1, 1)
            With rng
                .Value = lenCount
                .Interior.Color = RGB(192, 192, 128)
                .Offset(0, 1).Interior.Color = RGB(192, 192, 128)
            End With
    
            Call Test(lenCount, rng)
    
            With rng
                .Interior.ColorIndex = 0
                .Offset(0, 1).Interior.ColorIndex = 0
            End With
        Next
    
        wkSht.Activate
    End Sub
    
    

    좋은 웹페이지 즐겨찾기