我如何进行 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 个问题:
- 即使在编译器中使用 ARITH(EXTEND) 选项,COBOL 也无法处理大于 31 位数字的数字字段,而我的程序将处理这种情况。我的 DIGITIZED-STRING 字段的长度为 66 是有原因的。当我编译我的程序时,我收到这条消息:
"Truncation of high-order digit positions may occur due to precision
of intermediate results exceeding 31 digits."
- 当我的 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).
尝试用更少的代码使用更长的数字更有效。
我正在编写一个将国际帐号转换为标准 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 个问题:
- 即使在编译器中使用 ARITH(EXTEND) 选项,COBOL 也无法处理大于 31 位数字的数字字段,而我的程序将处理这种情况。我的 DIGITIZED-STRING 字段的长度为 66 是有原因的。当我编译我的程序时,我收到这条消息:
"Truncation of high-order digit positions may occur due to precision of intermediate results exceeding 31 digits."
- 当我的 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).
尝试用更少的代码使用更长的数字更有效。