0

私は、この RosettaCode チャレンジのブルート フォース実装に取り​​組んでいました。USAGE BINARY-DOUBLE よりも大きな数値を処理できるようにしたかったので、加算用の非常に単純な bignum ルーチンを作成しました。

特定の反復回数に制限したい場合、その回数が 9(18) より大きい場合、それは難しいことです。そこで、配列の特定の要素に 88 というアイデアを思いついたので、以下のコードを作成しました。

       03  DIGITS1 OCCURS 40 TIMES PIC 9.
       03  FILLER REDEFINES DIGITS1.
           05 FILLER pic 9999999999.
           05 FILLER pic 999999999.
           05 filler pic 9.
               88 EOR value 1.
           05 filler pic 9999999999.
           05 filler pic 9999999999.

したがって、これが唯一の方法なのか、それとも 10^20 になったときに他の方法があるのか​​ 、まだ疑問に思っています。

これが完全な「解決策」です。めちゃくちゃですが、ほとんど機能しています。

   identification division.
   program-id. Program1.

   data division.
   working-storage section.
   01  COUNTER.
       03  DIGITS1 OCCURS 40 TIMES PIC 9.
       03  FILLER REDEFINES DIGITS1.
           05 filler pic 9999999999.
           05 FILLER pic 9999999999.
           05 filler pic 9999999999.
           05 filler pic 999.
           05 filler pic 9.
               88 EOR value 1.
           05 filler pic 999999.

   01  INCREMENTOR.
       03  DIGITS1 OCCURS 40 TIMES PIC 9.

   01  ACCUMULATOR.
       03  DIGITS1 OCCURS 40 TIMES PIC 9.

   01  IN-NUMBER   usage binary-double unsigned.
   01  I               USAGE BINARY-DOUBLE UNSIGNED.
   01  N               USAGE BINARY-DOUBLE UNSIGNED.
   01  THREE-COUNTER   USAGE BINARY-CHAR value 1.
       88 IS-THREE VALUE 3.
   01  FIVE-COUNTER    USAGE BINARY-CHAR value 1.
       88 IS-FIVE VALUE 5.
   01  ANSWER pic x(40).       
   procedure division.
       initialize COUNTER ACCUMULATOR incrementor.
   10-MAIN-PROCEDURE.
       move 1 to IN-NUMBER.
       call "MOVENUMTOBIGNUM" using by content in-number 
           by reference incrementor.
       move 1 to IN-NUMBER.
       call "MOVENUMTOBIGNUM" using by content in-number 
           by reference counter.
       PERFORM 20-INNER-LOOP WITH TEST AFTER UNTIL eor.
       move ACCUMULATOR to ANSWER.
       inspect answer REPLACING LEADING '0'
        by space.
       DISPLAY answer.
       STOP RUN.
   20-INNER-LOOP.
       IF IS-THREE OR IS-FIVE
           call "ADDBIGNUMS" using by content counter
            by reference accumulator
           IF IS-THREE
               MOVE 1 TO THREE-COUNTER
           ELSE
               ADD 1 TO THREE-COUNTER
           END-IF
           IF IS-FIVE
               MOVE 1 TO FIVE-COUNTER
           ELSE    
               ADD 1 TO FIVE-COUNTER
           END-IF
       ELSE
           ADD 1 TO FIVE-COUNTER END-ADD
           ADD 1 TO THREE-COUNTER END-ADD
       END-IF.
       call "ADDBIGNUMS" using by content INCREMENTOR 
        by reference counter.
       EXIT.
   end program Program1.

   identification division.
   PROGRAM-ID. MOVENUMTOBIGNUM.
   ENVIRONMENT DIVISION.
   DATA DIVISION.
   WORKING-STORAGE SECTION.
   01  num-MOD   usage binary-CHAR.
   01  num-DIV   usage binary-DOUBLE unsigned.
   01  IN-COUNTER  usage binary-char.
   LINKAGE SECTION.
   01  num usage binary-double.
   01  BIGNUM.
       03  DIGITS1 OCCURS 40 TIMES PIC 9.

   PROCEDURE DIVISION USING NUM BIGNUM.
   10-MOVE.
       move 40 to IN-COUNTER.
       perform until num = 0
           divide num by 10 
               giving num-DIV 
               REMAINDER num-MOD
           end-divide
           move num-MOD to DIGITS1 of BIGNUM(IN-COUNTER)
           move NUM-DIV to NUM
           subtract 1 from IN-COUNTER end-subtract
       END-PERFORM.
       GOBACK.
   END PROGRAM MOVENUMTOBIGNUM.

  *Add Bignum to Bignum, modifying second Bignum in situ
   identification division.
   program-id. ADDBIGNUMS.
   DATA DIVISION.
   WORKING-STORAGE SECTION.
   01 IN-COUNTER usage binary-char.
   01  ADD-FLAG    pic 9.
       88 STILL-ADDING VALUE 0.
       88 DONE-ADDING VALUE 9.
   01  CARRIER usage binary-char.
   01  REGISTER-A usage binary-char.

   LINKAGE SECTION.
   01  BIGNUM1.
       03  DIGITS1 OCCURS 40 TIMES PIC 9.
   01  BIGNUM2.
       03  DIGITS1 OCCURS 40 TIMES PIC 9.

   PROCEDURE DIVISION USING BIGNUM1 BIGNUM2.
   10-ADD-WITH-CARRY.
       move zero to CARRIER.
       move 40 to IN-COUNTER.
       move zero to ADD-FLAG.
       perform until DONE-ADDING
           add DIGITS1 of BIGNUM1(IN-COUNTER)
           DIGITS1 of BIGNUM2(IN-COUNTER)
           CARRIER GIVING REGISTER-A 
           END-ADD
           move zero to CARRIER
           if REGISTER-A > 9 
               divide REGISTER-A by 10 
                   giving CARRIER 
                   remainder REGISTER-A
               end-divide
            else
               if REGISTER-A = zero
                   move 9 to ADD-FLAG
               END-IF
            end-if
            if STILL-ADDING
               move REGISTER-A to DIGITS1 of BIGNUM2(IN-COUNTER)
               subtract 1 from IN-COUNTER end-subtract
            end-if
       END-PERFORM.
       goback.
   END PROGRAM ADDBIGNUMS.
4

1 に答える 1

1

あなたはすでに構造が気に入らないようですが、私はそれに固執します。それはあなたの構造でも機能します。REDEFINES やその他の FILLER は必要ありません。

   05  FILLER.
       10  FILLER OCCURS 40 TIMES.
            15  DIGITS1                   PIC 9.
                88  DIGITS1-MEANS-SOMETHING
                                          VALUE 1.

01  NAME-THAT-REVEALS-INFORMATION BINARY  PIC 9(4).

    IF DIGITS1-MEANS-SOMETHING
        ( NAME-THAT-REVEALS-INFORMATION )
        do some stuff
    END-IF

PIC 9 を PIC X に変更しました。計算を行う場合を除き、フィールドを「数値」の 9 として定義する必要はありません。フィールドに数値が含まれていたり、名前に数値などの単語が含まれている場合は、だまされて数値として定義しないでください。

余分な(生成された)コードが続き、「これで数値的な処理が行われる」という意味を持っているため、誤解を招きます。出力のために「数値編集」を行う必要がある場合は、その時点で常に R​​EDEFINES があります。それを実現するために、これらの他のコストは必要ありません。

編集後、PIC 9 を計算に使用していることがわかります :-)

于 2015-11-09T06:53:08.610 に答える