COBOLの符号付きの数字項目について、文字コード(バイナリ)だとどのように値を保持しているのかの解説が英語しかなかったので、記事を書きます。
符号付きの数字項目は「PIC S9(03)」のように定義するのですが、符号を示す「S」が付いたからといってバイト数が増えることはありません。
では、どのようにして符号の情報を保持しているのでしょうか。
英語では以下の文献があります。
EBCDIC to ASCII Conversion of IBM Signed Fields (Zoned, Over-punched Fields) - A Disc Interchange technical article
http://www.3480-3590-data-conversion.com/article-signed-fields.html
メインフレーム(ホストコンピュータ)の世界で良く使われる文字コードとしてEBCDICという文字コードがあるのですが、EBCDICでは以下のように値を保持します。
バイナリ | 実際の値 |
F0 | 0 |
F1 | 1 |
F2 | 2 |
F3 | 3 |
F4 | 4 |
F5 | 5 |
F6 | 6 |
F7 | 7 |
F8 | 8 |
F9 | 9 |
符号無しの数値項目の場合は、これを単純に並べるだけです。
例えば、「120」は、「F1 F2 F0」のように値を保持します。
符号有りの数値項目の場合は、最後の桁について、上位4ビットを変更することで符号を表現します。
「+」を表現する時は「F」の箇所が「C」になりますし、「-」を表現する時は「F」の箇所が「D」になります。
例えば、「+120」は「F1 F2 C0」になりますし、「-120」は「F1 F2 D0」になります。
(ただし、「+」の場合は、「C」にせずに「F」のままセットされることも多いです。「C」にならなかったとしても慌てないでください。)
ちなみに、ここまでの話はゾーン10進数の話です。
パック10進数については既に記事を書いていますので、以下の記事を参照して下さい。
COBOLにおけるパック10進数(COMP-3)のデータの持ち方 - 技術とか戦略とか
https://akira2kun.hatenablog.com/entry/2018/10/01/014401
-------------------------------
以下、opensource COBOL で試してみた結果です。
opensource COBOL ではASCIIコードで出力され、ASCIIコードの場合の符号無し数値項目(ゾーン10進数)は上位4ビットが「3」になるのですが、「-」の場合は上位4ビットが「7」になるようです。「+」の場合は符号無し数値項目の場合と変わりませんでした。
なお、パック10進数の場合はEBCDICの場合と値の持ち方は同じです。
【テストコード】
IDENTIFICATION DIVISION.
PROGRAM-ID. SIGNTEST.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT F1 ASSIGN TO "C:\tmp\a.txt".
*
DATA DIVISION.
FILE SECTION.
FD F1.
01 F1R.
03 F1-REC PIC X(52).
*
WORKING-STORAGE SECTION.
01 F1-REC-WORK.
03 F1-REC1 PIC 9(10) VALUE 1234567890.
03 KAIGYO1 PIC X(02) VALUE X"0D0A".
03 F1-REC2 PIC S9(10) VALUE +1234567890.
03 KAIGYO2 PIC X(02) VALUE X"0D0A".
03 F1-REC3 PIC S9(10) VALUE -1234567890.
03 KAIGYO3 PIC X(02) VALUE X"0D0A".
03 F1-REC4 PIC S9(10) COMP-3 VALUE +1234567890.
03 KAIGYO4 PIC X(02) VALUE X"0D0A".
03 F1-REC5 PIC S9(10) COMP-3 VALUE -1234567890.
03 KAIGYO5 PIC X(02) VALUE X"0D0A".
*
PROCEDURE DIVISION.
*
* 各種処理の呼び出し
*
000-CONTROLLER-S.
PERFORM 100-START-S THRU 100-START-E.
PERFORM 200-MAIN-S THRU 200-MAIN-E.
PERFORM 300-END-S THRU 300-END-E.
STOP RUN.
000-CONTROLLER-E.
*
* 前処理
*
100-START-S.
OPEN OUTPUT F1.
100-START-E.
*
* 主処理
*
200-MAIN-S.
MOVE F1-REC-WORK TO F1-REC.
WRITE F1R.
200-MAIN-E.
*
* 後処理
*
300-END-S.
CLOSE F1.
300-END-E.
【実行結果】