数字数组中特定数字的88级?

时间:2015-11-09 06:38:25

标签: cobol gnucobol

我正在努力实施this RosettaCode challenge的蛮力实施。我希望能够处理大于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.

1 个答案:

答案 0 :(得分:0)

虽然你似乎不喜欢这种结构,但我会坚持下去。它也适用于您的结构。不需要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。如果某个字段碰巧包含数字,或者碰巧有字号或其名称中的字母,请不要欺骗将其定义为数字。

额外的(生成的)代码随之而来,它带有“数字内容将用此完成”的含义,因此误导。如果/当你需要对输出进行“数字编辑”时,那时总是有REDEFINES。没有这些其他成本来实现这一目标。

我现在已经恢复到你的PIC 9,因为在编辑之后,我可以看到你正在使用它进行计算: - )