我如何进行 MOD 97 计算

How do I do the MOD 97 calculation

我正在编写一个将国际帐号转换为标准 IBAN 结构的程序。

到目前为止,我已经设法编写了一个程序来检查输入的有效性,将输入的字符串串在一起而不嵌入空格或零,将字母字符转换为与其在字母表中的位置相对应的数字,并用这些创建一个字符串数字。

现在我要做的就是计算数字的Mod 97,然后从98中减去余数。如果结果是个位数,那么我必须插入一个前导零。

我现在有的是:

注意:我在这一步之前使用指针将数字放入字符串中,因此指针(从中减去 1 后)包含字符串的总长度。

WORKING STORAGE SECTION.
01 WORK-FIELDS.
   05  HELP FIELDS.
       10  POINTER                PIC S9(04)           COMP.
       10  DIGITIZED-STRING       PIC X(66).
       10  STRING-FOR-CALCULATION PIC 9(31).

   05  IBAN.
       10 COUNTRY-CODE            PIC X(02).
       10 CHECK-DIGITS            PIC 9(02).
       10 BANK-CODE               PIC X(10).
       10 BRANCH-CODE             PIC X(10).
       10 ACCOUNT-NUMBER          PIC X(28).
       10 OUTPUT-IBAN             PIC X(34). 


PROCEDURE DIVISION.

SUBTRACT 1 FROM POINTER
           STRING DIGITIZED-STRING(1:POINTER)
                  DELIMITED BY SIZE
                  INTO STRING-FOR-CALCULATION
           EVALUATE TRUE
               WHEN POINTER < 32
                    COMPUTE IBAN-CHECK-DIGITS = 98
                    - FUNCTION MOD(STRING-FOR-CALCULATION, 97)
           END-EVALUATE
           .

我有 2 个问题:

  1. 即使在编译器中使用 ARITH(EXTEND) 选项,COBOL 也无法处理大于 31 位数字的数字字段,而我的程序将处理这种情况。我的 DIGITIZED-STRING 字段的长度为 66 是有原因的。当我编译我的程序时,我收到这条消息:

"Truncation of high-order digit positions may occur due to precision of intermediate results exceeding 31 digits."

  1. 当我的 STRING-FOR-CALCULATION 字段的长度(如上所示)比我从 DIGITIZED-STRING 移动到它的内容长时,间隙由尾随零填充。这会影响计算。当我手动将 STRING-FOR-CALCULATION 字段调整为与 DIGITIZED-STRING 的内容一样长时,计算进行得很顺利。

我只是不知道如何确保它在我处理更短和更长的数字时有效,我必须将它们分成几部分。

附加信息:

我使用此文档作为指南:www.bpfi.ie/wp-content/uploads/2014/10/MOD-97-Final-May-2013.pdf

但我不知道如何在 COBOL 中执行此操作。

此外,对于那些阅读并回答了我之前的问题的人来说,这些字段不是全国性的是因为我的项目经理改变了主意。现在我所要做的就是使用 MOVE FUNCTION NATIONAL-OF 将 IBAN-OUTPUT 字段移动到 copybook。

更新

我正在使用 COBOL/390 编译器。

下面是我最终使用的代码:

WORKING-STORAGE SECTION.

01   DIGITIZED-STRING                  PIC X(66).
01   POINTER                           PIC S9(04)           COMP.

01   TEST-FIELDS.
            05  VERY-LONG-NUMBER.
                10  VLN-FIRST-PART     PIC 9(11).
                10  VLN-SECOND-PART    PIC 9(11).
                10  VLN-THIRD-PART     PIC 9(11).
                10  VLN-FOURTH-PART    PIC 9(11).
                10  VLN-FIFTH-PART     PIC 9(11).
                10  VLN-SIXTH-PART     PIC 9(11).
            05  EXPANDED-DIVIDEND                    PIC 9(13).
            05  FILLER
                REDEFINES EXPANDED-DIVIDEND.
                10  ED-REMAINDER                     PIC 99.
                10  ED-PART                          PIC 9(11).
            05  IRRELEVANT-ANSWER                    PIC 9(12).



PROCEDURE DIVISION.
MOVE SPACES TO TEST-FIELDS
           MOVE ZEROES TO TEST-FLDS
           MOVE DIGITIZED-STRING(1:POINTER)
                TO VERY-LONG-NUMBER(66 - POINTER + 1:POINTER)

               MOVE ZERO                    TO ED-REMAINDER
               MOVE VLN-FIRST-PART          TO ED-PART
               DIVIDE EXPANDED-DIVIDEND     BY 97
                 GIVING                     IRRELEVANT-ANSWER
                 REMAINDER                  ED-REMAINDER
               MOVE VLN-SECOND-PART         TO ED-PART
               DIVIDE EXPANDED-DIVIDEND     BY 97
                 GIVING                       IRRELEVANT-ANSWER
                 REMAINDER                    ED-REMAINDER
               MOVE VLN-THIRD-PART          TO ED-PART
               DIVIDE EXPANDED-DIVIDEND     BY 97
                 GIVING                       IRRELEVANT-ANSWER
                 REMAINDER                    ED-REMAINDER
               MOVE VLN-FOURTH-PART         TO ED-PART
               DIVIDE EXPANDED-DIVIDEND     BY 97
                 GIVING                       IRRELEVANT-ANSWER
                 REMAINDER                    ED-REMAINDER
               MOVE VLN-FIFTH-PART         TO ED-PART
               DIVIDE EXPANDED-DIVIDEND     BY 97
                 GIVING                       IRRELEVANT-ANSWER
                 REMAINDER                    ED-REMAINDER
               MOVE VLN-SIXTH-PART         TO ED-PART
               DIVIDE EXPANDED-DIVIDEND     BY 97
                 GIVING                       IRRELEVANT-ANSWER
                 REMAINDER                    ED-REMAINDER

           COMPUTE CHECK-DIGITS = 98
                   - ED-REMAINDER
           .

你喜欢"long division"。

1234 divided by 97 =
123 divided by 97, which gives x (doesn't matter for you) remainder 26
264 divided by 97, gives x, remainder 70

70 是 1234 的 mod 97。

这是一个示例程序:

   ID DIVISION. 
   PROGRAM-ID. STAB22. 
   DATA DIVISION. 
   WORKING-STORAGE SECTION. 
   01  VERY-LONG-NUMBER                     PIC 9(8). 
   01  FILLER 
       REDEFINES VERY-LONG-NUMBER. 
       05  VLN-FIRST-PART                   PIC 9(4). 
       05  VLN-SECOND-PART                  PIC 9(4). 
   01  EXPANDED-DIVIDEND                    PIC 9(6). 
   01  FILLER 
       REDEFINES EXPANDED-DIVIDEND. 
       05  ED-REMAINDER                     PIC 99. 
       05  ED-PART                          PIC 9(4). 
   01  IRRELEVANT-ANSWER                    PIC 9(5). 
   01  VALUE-FOR-MOD-97      PACKED-DECIMAL PIC 99 VALUE 97.
   PROCEDURE DIVISION. 
       MOVE 1234                    TO VERY-LONG-NUMBER 
       MOVE ZERO                    TO ED-REMAINDER 
       MOVE VLN-FIRST-PART          TO ED-PART 
       DIVIDE EXPANDED-DIVIDEND     BY VALUE-FOR-MOD-97 
         GIVING                     IRRELEVANT-ANSWER 
         REMAINDER                  ED-REMAINDER 
       MOVE VLN-SECOND-PART         TO ED-PART 
       DIVIDE EXPANDED-DIVIDEND     BY VALUE-FOR-MOD-97 
         GIVING                     IRRELEVANT-ANSWER 
         REMAINDER                  ED-REMAINDER 
       DISPLAY ED-REMAINDER 
       MOVE 12345678                TO VERY-LONG-NUMBER 
       MOVE ZERO                    TO ED-REMAINDER 
       MOVE VLN-FIRST-PART          TO ED-PART 
       DIVIDE EXPANDED-DIVIDEND     BY VALUE-FOR-MOD-97 
         GIVING                     IRRELEVANT-ANSWER 
         REMAINDER                  ED-REMAINDER 
       MOVE VLN-SECOND-PART         TO ED-PART 
       DIVIDE EXPANDED-DIVIDEND     BY VALUE-FOR-MOD-97 
         GIVING                     IRRELEVANT-ANSWER 
         REMAINDER                  ED-REMAINDER 
       DISPLAY ED-REMAINDER 
       GOBACK 
       . 

结果为 70 和 03。

你推断。我建议你有六个部分的 11 位数字,每次都产生 13 位数字的红利。这将比使用编译器选项 ARITH(EXTEND).

尝试用更少的代码使用更长的数字更有效。