0

PR-ACT-SOURCE-DETAIL-1 と PR-ACT-SOURCE-DETAIL-2 という 2 つの文字列があるとします。この2つの文字列を比較して、違いが見つかった位置を見つけたいです。

私はこのようにシナリオを処理しようとしました -

 PERFORM VARYING N FROM 1 BY 1 UNTIL N > 5000                                                                  
    IF PR-ACT-SOURCE-DETAIL-1 OF TRANSACTION-RECORD-1(N:1)   
        IS NOT EQUAL TO                                    
       PR-ACT-SOURCE-DETAIL-2 OF TRANSACTION-RECORD-2(N:1)  

        MOVE 'Y' TO WS-DIFF-FOUND   
        DISPLAY 'DIFFERENCE FOUND AT POSITION' N
    END-IF
 END-PERFORM

上記のコードの問題は、実行ループが 5000 回発生し、そのような 10,000 個の文字列を比較する必要がある場合、実行時間が長くなりすぎることです。

より短い実行時間を必要とする同じことを行う他の方法はありますか?

4

4 に答える 4

0

以下のプログラムは、それぞれ 2 つのバリエーションを持つ 2 つの異なるメソッドを使用します。

  1. PIC 9 をインデックスとして使用するシーケンシャル
  2. インデックスとしてPIC s9 COMP-5を使用したシーケンシャル
  3. 二分探索
  4. ループの少ない二分探索

最悪の場合(最終バイトの違い)

  • 方法 2 は、ネイティブ データ項目を使用するため、方法 1 よりも約 1.5 倍高速です。
  • 方法 3 は方法 1 よりも約 11 倍高速です

ノート:

  • 差が最初の 250 バイトにある場合、二分検索は順次検索よりも遅くなります。
  • 方法 3 と 4 は同等です
  • パフォーマンスは、COBOL ランタイムの実装によって影響を受ける場合があります。

互換性:

  • ANSI-85 で定義されている EXIT PERFORM ステートメント。
  • COMP-5 は ANSI ではなく (ただし、ほとんどすべてのコンパイラでサポートされています)、BINARY-LONG を表す使用法に置き換えることができます。

コード:

   PROGRAM-ID. COMPSTR.
   WORKING-STORAGE SECTION.
   01 N PIC S9(9) COMP-5.
   01 N1 PIC 9(9).
   01 STRLEN PIC S9(9) COMP-5.
   01 CMPLEN PIC S9(9) COMP-5.
   01 CHUNK-BASE-OFFSET PIC S9(9) COMP-5.
   01 CHUNK-BASE-LENGTH PIC S9(9) COMP-5.
   01 CHUNK-OFFSET PIC S9(9) COMP-5.
   01 CHUNK-LENGTH PIC S9(9) COMP-5.
   01 STR1 PIC X(5000).
   01 STR2 PIC X(5000).
   01 WS-DIFF-FOUND PIC X.

   01 DIFF-TIME PIC 9(7)V99 COMP-5.
   01 EMPTY-PERFORM-TIME PIC 9(7)V99 COMP-5.
   78 LOOPS VALUE 10000.
   01 START-TIME.
      03 START-H PIC 99.
      03 START-M PIC 99.
      03 START-S PIC 99.
      03 START-T PIC 99.
   01 END-TIME.
      03 END-H PIC 99.
      03 END-M PIC 99.
      03 END-S PIC 99.
      03 END-T PIC 99.
   01 X PIC X.
   PROCEDURE DIVISION.
   MAIN-LOGIC.
       MOVE 5000 TO STRLEN

       ACCEPT START-TIME FROM TIME
       PERFORM LOOPS TIMES
           PERFORM EMPTY-PERFORM
       END-PERFORM
       ACCEPT END-TIME FROM TIME
       PERFORM TIME-DIFF
       MOVE DIFF-TIME TO EMPTY-PERFORM-TIME
       DISPLAY "EMPTY-PERFORM: " EMPTY-PERFORM-TIME

       MOVE ALL SPACES TO STR1 STR2
       MOVE "X" TO STR2(5000:1)
       PERFORM TEST-ALL

       MOVE ALL SPACES TO STR1 STR2
       MOVE "X" TO STR2(1:1)
       PERFORM TEST-ALL

       MOVE ALL SPACES TO STR1 STR2
       MOVE "X" TO STR2(2500:1)
       PERFORM TEST-ALL

       MOVE ALL SPACES TO STR1 STR2
       MOVE "X" TO STR2(250:1)
       PERFORM TEST-ALL

       ACCEPT X
       EXIT PROGRAM
       STOP RUN
       .

   TEST-ALL.
       ACCEPT START-TIME FROM TIME
       PERFORM LOOPS TIMES
           PERFORM COMPARE-1
       END-PERFORM
       ACCEPT END-TIME FROM TIME
       PERFORM TIME-DIFF
       DISPLAY "COMPARE-1: " DIFF-TIME " DIFFERENCE AT: " N1

       ACCEPT START-TIME FROM TIME
       PERFORM LOOPS TIMES
           PERFORM COMPARE-2
       END-PERFORM
       ACCEPT END-TIME FROM TIME
       PERFORM TIME-DIFF
       DISPLAY "COMPARE-2: " DIFF-TIME " DIFFERENCE AT: " N

       ACCEPT START-TIME FROM TIME
       PERFORM LOOPS TIMES
           PERFORM COMPARE-3
       END-PERFORM
       ACCEPT END-TIME FROM TIME
       PERFORM TIME-DIFF
       DISPLAY "COMPARE-3: " DIFF-TIME " DIFFERENCE AT: " N

       ACCEPT START-TIME FROM TIME
       PERFORM LOOPS TIMES
           PERFORM COMPARE-4
       END-PERFORM
       ACCEPT END-TIME FROM TIME
       PERFORM TIME-DIFF
       DISPLAY "COMPARE-4: " DIFF-TIME " DIFFERENCE AT: " N
       .

   EMPTY-PERFORM.
       .

   COMPARE-1.
       PERFORM VARYING N1 FROM 1 BY 1 UNTIL N1 > 5000                                                                  
           IF STR1(N1:1) IS NOT EQUAL TO STR2(N1:1)
               MOVE 'Y' TO WS-DIFF-FOUND
               EXIT PERFORM
           END-IF
       END-PERFORM
       .

   COMPARE-2.
       PERFORM VARYING N FROM 1 BY 1 UNTIL N > 5000                                                                  
           IF STR1(N:1) IS NOT EQUAL TO STR2(N:1)
               MOVE 'Y' TO WS-DIFF-FOUND
               EXIT PERFORM
           END-IF
       END-PERFORM
       .

   COMPARE-3.
       IF STR1 = STR2
           MOVE 0 TO N
       ELSE
           MOVE 1 TO CMPLEN
           PERFORM UNTIL CMPLEN >= STRLEN
              COMPUTE CMPLEN = CMPLEN * 2
           END-PERFORM
           MOVE 1 TO CHUNK-BASE-OFFSET
           COMPUTE CHUNK-BASE-LENGTH = CMPLEN / 2
           PERFORM UNTIL 1 = 2
               MOVE CHUNK-BASE-OFFSET TO CHUNK-OFFSET
               MOVE CHUNK-BASE-LENGTH TO CHUNK-LENGTH
               PERFORM 2 TIMES
                   IF CHUNK-OFFSET + CHUNK-LENGTH - 1 > STRLEN
                       COMPUTE CHUNK-LENGTH =
                               STRLEN - CHUNK-OFFSET + 1
                   END-IF
                   IF STR1(CHUNK-OFFSET:CHUNK-LENGTH)
                        IS NOT EQUAL TO
                        STR2(CHUNK-OFFSET:CHUNK-LENGTH)
                       MOVE CHUNK-OFFSET TO CHUNK-BASE-OFFSET
                       COMPUTE CHUNK-BASE-LENGTH =
                               CHUNK-BASE-LENGTH / 2
                       EXIT PERFORM
                   ELSE
                       ADD CHUNK-LENGTH TO CHUNK-OFFSET
                   END-IF
               END-PERFORM
               IF CHUNK-BASE-LENGTH = 0
                   EXIT PERFORM
               END-IF
           END-PERFORM
           MOVE CHUNK-OFFSET TO N
       END-IF
       .

   COMPARE-4.
       IF STR1 = STR2
           MOVE 0 TO N
       ELSE
           MOVE 1 TO CMPLEN
           PERFORM UNTIL CMPLEN >= STRLEN
              COMPUTE CMPLEN = CMPLEN * 2
           END-PERFORM
           MOVE 1 TO CHUNK-BASE-OFFSET
           COMPUTE CHUNK-BASE-LENGTH = CMPLEN / 2
           PERFORM UNTIL 1 = 2
               MOVE CHUNK-BASE-OFFSET TO CHUNK-OFFSET
               MOVE CHUNK-BASE-LENGTH TO CHUNK-LENGTH
               PERFORM 2 TIMES
                   IF CHUNK-OFFSET + CHUNK-LENGTH - 1 > STRLEN
                       COMPUTE CHUNK-LENGTH =
                               STRLEN - CHUNK-OFFSET + 1
                   END-IF
                   IF STR1(CHUNK-OFFSET:CHUNK-LENGTH)
                        IS NOT EQUAL TO
                        STR2(CHUNK-OFFSET:CHUNK-LENGTH)
                       MOVE CHUNK-OFFSET TO CHUNK-BASE-OFFSET
                       PERFORM UNTIL CHUNK-BASE-LENGTH <
                                     CHUNK-LENGTH
                           COMPUTE CHUNK-BASE-LENGTH =
                                   CHUNK-BASE-LENGTH / 2
                       END-PERFORM
                       EXIT PERFORM
                   ELSE
                       ADD CHUNK-LENGTH TO CHUNK-OFFSET
                   END-IF
               END-PERFORM
               IF CHUNK-BASE-LENGTH = 0
                   EXIT PERFORM
               END-IF
           END-PERFORM
           MOVE CHUNK-OFFSET TO N
       END-IF
       .

   TIME-DIFF.
       COMPUTE DIFF-TIME = (END-H - START-H) * 3600 +
                           (END-M - START-M) * 60 +
                           (END-S - START-S) +
                           (END-T - START-T) / 100
       .
于 2013-10-02T13:15:47.443 に答える