写入数据集后 Cobol COMP-3 值发生变化
Cobol COMP-3 value changes after write to dataset
已解决
我发现这条线隐藏在我将这些值移动到输出文件的地方:
INSPECT OUT-RECORD REPLACING ALL X'00' BY ' '
将我的 X'00' 更改为 X'40',这是我得到神秘的 '4' 的地方。我将这归因于我的第一个 Cobol 版本缺少“;”。
感谢Bruce和匿名用户user9835153的帮助!
我需要一些帮助来解决我以前从未遇到过的奇怪情况。
我有一个无符号分区十进制数字作为输入,PIC 9(3).9(6),我需要将它作为带符号的 COMP-3,PIC S9(3)V9( 6).这适用于所有值 ,除非输入 中的小数点周围有零。在这种情况下,小数点前的 0 始终更改为 4。
示例:当输入值为31.006261时,它被写为+31.006261(实际输出文件中的x'031006261C')。但是,当输入值为 30.006261 时,它会作为 +34.006261 (x'034006261C') 写入文件。
我无法更改值的输入方式,但可以更改输入布局。我尝试了多种移动此值的方法,包括:从输入直接移动到 COMP-3,移动到工作存储中不同类型的临时字段,使输入成为字符字段并移动到数字(完全忽略小数) .
这是我正在做的事情的简化版本:
* Value 30.006261 is read into WS-IN-VAL from input file.
01 WS-IN-RECORD.
05 WS-IN-VAL PIC 9(3).9(6).
01 OUT-RECORD.
05 WS-OUT-VAL PIC S9(3)V9(6) COMP-3.
* Working Storage 01 area
05 WS-HOLD-VAL PIC 9(3)V9(6).
05 WS-DISP-VAL PIC +9(3).9(6).
MOVE WS-IN-VAL TO WS-HOLD-VAL.
MOVE WS-HOLD-VAL TO WS-OUT-VAL.
MOVE WS-OUT-VAL TO WS-DISP-VAL.
WRITE WS-OUT-RECORD.
DISPLAY 'VALUE IN: ' WS-IN-VAL.
DISPLAY 'HOLD VALUE: ' WS-HOLD-VAL.
DISPLAY 'VALUE OUT: ' WS-OUT-VAL.
DISPLAY 'FORMATTED: ' WS-DISP-VAL.
VALUE IN: 30.006261
HOLD VALUE: 030006261
VALUE OUT: 030006261
FORMATTED: +030.006261
但是,当我使用 HEX ON 打开输出文件时,我得到的是:
----+
04021
3066C
View of the file with a layout shows: +34.006261.
每次小数点周围都是零时都会发生这种情况。我使用了 8 条记录的数据子集,并将一半更改为 10.1xxxxx,将另一半更改为 10.0xxxxx(x 是各种数字)。所有 10.0xxxxx 记录都更改为 14.0xxxxx,但 10.1xxxxx 记录保持正确。使用 20.x、30.x、40.x 等进行此操作并得到相同的结果。
从无符号变为有符号时,我也尝试使用 COMPUTE 而不是 MOVE —— 结果相同。就像我之前提到的,我尝试了各种移动输入值的方法,但结果总是一样的。我认为可能部分显式小数 (x'4B') 以某种方式被放置在高位半字节中,因此我修改了输入以单独读取它,并将其十六进制值更改为 x'00',但这没有用任何一个。我完全不知道还有什么可以尝试,也找不到其他经历过这种情况的人。
关于为什么小数点前的 0 被 4 代替,有什么想法或建议吗?
在提供建议后编辑 5/21/18:
VALUE FROM FILE: 50.022287
VALUE AFTER MOVE: 050022287
VALUE AS COMP-3 (OUTPUT FLD): 050022287
OUTPUT DISPLAYED: +050.022287
VALUE IN FILE: +54.022287
写入数据集后小数点前的零仍然变化。
在 Cobol 的早期版本中 9(3).9(6) 将是一个 Edited-numeric -> 字符字段。我不确定当前的标准/ibm 实现应该做什么,您可以查看 IBM/IBM 手册以了解应该发生的事情。
我可能会将其编码为
01 WS-IN-RECORD.
05 WS-IN-VAL PIC 9(3).9(6).
05 redefines WS-IN-VAL.
10 WS-IN-VAL-pt1 pic 9(3)
10 pic x.
10 WS-IN-VAL-Decimal pic v9(6)
和
Add WS-IN-VAL-pt1 to WS-IN-VAL-Decimal
Giving ...
可能的实验
尝试定义
01 WS-IN-RECORD.
05 WS-IN-VAL-X.
10 WS-IN-VAL PIC 9(3).9(6).
并尝试将 WS-IN-VAL-X 和 WS-IN-VAL 移入,看看结果是否相同
这是在 IBM Enterprise COBOL 下为 z/OS 4.2.0 编译和 运行 的完整 COBOL 程序。它不显示您所描述的行为:
IDENTIFICATION DIVISION.
PROGRAM-ID. COMP3.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OFILE ASSIGN TO OFILE STATUS OFILE-STAT.
DATA DIVISION.
FILE SECTION.
FD OFILE
LABEL RECORDS STANDARD
RECORDING MODE F
BLOCK CONTAINS 0 RECORDS.
01 OFILE-REC.
02 COMP3-NBR PIC S9(3)V9(6) COMP-3.
02 PIC X(75).
WORKING-STORAGE SECTION.
01 WS-IN-VAL PIC 9(3).9(6).
01 WS-OUT-VAL PIC S9(3)V9(6) COMP-3.
01 WS-OUT-VAL-X REDEFINES WS-OUT-VAL
PIC X(5).
01 WS-HOLD-VAL PIC 9(3).9(6).
01 WS-DISP-VAL PIC +9(3).9(6).
01 OFILE-STAT PIC 9(2).
88 OFILE-STAT-OK VALUE ZERO.
PROCEDURE DIVISION.
MOVE 30.006216 TO WS-IN-VAL
MOVE WS-IN-VAL TO WS-HOLD-VAL
MOVE WS-HOLD-VAL TO WS-OUT-VAL
02 PIC X(75).
WORKING-STORAGE SECTION.
01 WS-IN-VAL PIC 9(3).9(6).
01 WS-OUT-VAL PIC S9(3)V9(6) COMP-3.
01 WS-OUT-VAL-X REDEFINES WS-OUT-VAL
PIC X(5).
01 WS-HOLD-VAL PIC 9(3).9(6).
01 WS-DISP-VAL PIC +9(3).9(6).
01 OFILE-STAT PIC 9(2).
88 OFILE-STAT-OK VALUE ZERO.
PROCEDURE DIVISION.
MOVE 30.006216 TO WS-IN-VAL
MOVE WS-IN-VAL TO WS-HOLD-VAL
MOVE WS-HOLD-VAL TO WS-OUT-VAL
MOVE WS-OUT-VAL TO WS-DISP-VAL
DISPLAY 'VALUE IN: ' WS-IN-VAL
DISPLAY 'HOLD VAL: ' WS-HOLD-VAL
DISPLAY 'OUT VAL : ' WS-OUT-VAL
DISPLAY 'OUT VALX: ' WS-OUT-VAL-X
OPEN OUTPUT OFILE
IF NOT OFILE-STAT-OK THEN
DISPLAY "OFILE OPEN STATUS: " OFILE-STAT
STOP RUN
END-IF
INITIALIZE OFILE-REC
MOVE WS-OUT-VAL TO COMP3-NBR
WRITE OFILE-REC
IF NOT OFILE-STAT-OK THEN
DISPLAY "OFILE WRITE STATUS: " OFILE-STAT
STOP RUN
END-IF
GOBACK
.
系统输出:
******************************** Top of Data ***********************************
VALUE IN: 030.006216
HOLD VAL: 030.006216
OUT VAL : 030006216
OUT VALX: : ::%
******************************* Bottom of Data ********************************
OFILE 内容以十六进制显示:
****** ***************************** Top of Data ******************************
000001 %
000260000000000000000000000000000000000000000000000000000000000000000000
3061C0000000000000000000000000000000000000000000000000000000000000000000
------------------------------------------------------------------------------
****** **************************** Bottom of Data ****************************
我觉得一切都很好!我认为您的代码中一定还有其他问题。
已解决
我发现这条线隐藏在我将这些值移动到输出文件的地方:
INSPECT OUT-RECORD REPLACING ALL X'00' BY ' '
将我的 X'00' 更改为 X'40',这是我得到神秘的 '4' 的地方。我将这归因于我的第一个 Cobol 版本缺少“;”。
感谢Bruce和匿名用户user9835153的帮助!
我需要一些帮助来解决我以前从未遇到过的奇怪情况。
我有一个无符号分区十进制数字作为输入,PIC 9(3).9(6),我需要将它作为带符号的 COMP-3,PIC S9(3)V9( 6).这适用于所有值 ,除非输入 中的小数点周围有零。在这种情况下,小数点前的 0 始终更改为 4。
示例:当输入值为31.006261时,它被写为+31.006261(实际输出文件中的x'031006261C')。但是,当输入值为 30.006261 时,它会作为 +34.006261 (x'034006261C') 写入文件。
我无法更改值的输入方式,但可以更改输入布局。我尝试了多种移动此值的方法,包括:从输入直接移动到 COMP-3,移动到工作存储中不同类型的临时字段,使输入成为字符字段并移动到数字(完全忽略小数) .
这是我正在做的事情的简化版本:
* Value 30.006261 is read into WS-IN-VAL from input file.
01 WS-IN-RECORD.
05 WS-IN-VAL PIC 9(3).9(6).
01 OUT-RECORD.
05 WS-OUT-VAL PIC S9(3)V9(6) COMP-3.
* Working Storage 01 area
05 WS-HOLD-VAL PIC 9(3)V9(6).
05 WS-DISP-VAL PIC +9(3).9(6).
MOVE WS-IN-VAL TO WS-HOLD-VAL.
MOVE WS-HOLD-VAL TO WS-OUT-VAL.
MOVE WS-OUT-VAL TO WS-DISP-VAL.
WRITE WS-OUT-RECORD.
DISPLAY 'VALUE IN: ' WS-IN-VAL.
DISPLAY 'HOLD VALUE: ' WS-HOLD-VAL.
DISPLAY 'VALUE OUT: ' WS-OUT-VAL.
DISPLAY 'FORMATTED: ' WS-DISP-VAL.
VALUE IN: 30.006261
HOLD VALUE: 030006261
VALUE OUT: 030006261
FORMATTED: +030.006261
但是,当我使用 HEX ON 打开输出文件时,我得到的是:
----+
04021
3066C
View of the file with a layout shows: +34.006261.
每次小数点周围都是零时都会发生这种情况。我使用了 8 条记录的数据子集,并将一半更改为 10.1xxxxx,将另一半更改为 10.0xxxxx(x 是各种数字)。所有 10.0xxxxx 记录都更改为 14.0xxxxx,但 10.1xxxxx 记录保持正确。使用 20.x、30.x、40.x 等进行此操作并得到相同的结果。
从无符号变为有符号时,我也尝试使用 COMPUTE 而不是 MOVE —— 结果相同。就像我之前提到的,我尝试了各种移动输入值的方法,但结果总是一样的。我认为可能部分显式小数 (x'4B') 以某种方式被放置在高位半字节中,因此我修改了输入以单独读取它,并将其十六进制值更改为 x'00',但这没有用任何一个。我完全不知道还有什么可以尝试,也找不到其他经历过这种情况的人。
关于为什么小数点前的 0 被 4 代替,有什么想法或建议吗?
在提供建议后编辑 5/21/18:
VALUE FROM FILE: 50.022287
VALUE AFTER MOVE: 050022287
VALUE AS COMP-3 (OUTPUT FLD): 050022287
OUTPUT DISPLAYED: +050.022287
VALUE IN FILE: +54.022287
写入数据集后小数点前的零仍然变化。
在 Cobol 的早期版本中 9(3).9(6) 将是一个 Edited-numeric -> 字符字段。我不确定当前的标准/ibm 实现应该做什么,您可以查看 IBM/IBM 手册以了解应该发生的事情。
我可能会将其编码为
01 WS-IN-RECORD.
05 WS-IN-VAL PIC 9(3).9(6).
05 redefines WS-IN-VAL.
10 WS-IN-VAL-pt1 pic 9(3)
10 pic x.
10 WS-IN-VAL-Decimal pic v9(6)
和
Add WS-IN-VAL-pt1 to WS-IN-VAL-Decimal
Giving ...
可能的实验
尝试定义
01 WS-IN-RECORD.
05 WS-IN-VAL-X.
10 WS-IN-VAL PIC 9(3).9(6).
并尝试将 WS-IN-VAL-X 和 WS-IN-VAL 移入,看看结果是否相同
这是在 IBM Enterprise COBOL 下为 z/OS 4.2.0 编译和 运行 的完整 COBOL 程序。它不显示您所描述的行为:
IDENTIFICATION DIVISION.
PROGRAM-ID. COMP3.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OFILE ASSIGN TO OFILE STATUS OFILE-STAT.
DATA DIVISION.
FILE SECTION.
FD OFILE
LABEL RECORDS STANDARD
RECORDING MODE F
BLOCK CONTAINS 0 RECORDS.
01 OFILE-REC.
02 COMP3-NBR PIC S9(3)V9(6) COMP-3.
02 PIC X(75).
WORKING-STORAGE SECTION.
01 WS-IN-VAL PIC 9(3).9(6).
01 WS-OUT-VAL PIC S9(3)V9(6) COMP-3.
01 WS-OUT-VAL-X REDEFINES WS-OUT-VAL
PIC X(5).
01 WS-HOLD-VAL PIC 9(3).9(6).
01 WS-DISP-VAL PIC +9(3).9(6).
01 OFILE-STAT PIC 9(2).
88 OFILE-STAT-OK VALUE ZERO.
PROCEDURE DIVISION.
MOVE 30.006216 TO WS-IN-VAL
MOVE WS-IN-VAL TO WS-HOLD-VAL
MOVE WS-HOLD-VAL TO WS-OUT-VAL
02 PIC X(75).
WORKING-STORAGE SECTION.
01 WS-IN-VAL PIC 9(3).9(6).
01 WS-OUT-VAL PIC S9(3)V9(6) COMP-3.
01 WS-OUT-VAL-X REDEFINES WS-OUT-VAL
PIC X(5).
01 WS-HOLD-VAL PIC 9(3).9(6).
01 WS-DISP-VAL PIC +9(3).9(6).
01 OFILE-STAT PIC 9(2).
88 OFILE-STAT-OK VALUE ZERO.
PROCEDURE DIVISION.
MOVE 30.006216 TO WS-IN-VAL
MOVE WS-IN-VAL TO WS-HOLD-VAL
MOVE WS-HOLD-VAL TO WS-OUT-VAL
MOVE WS-OUT-VAL TO WS-DISP-VAL
DISPLAY 'VALUE IN: ' WS-IN-VAL
DISPLAY 'HOLD VAL: ' WS-HOLD-VAL
DISPLAY 'OUT VAL : ' WS-OUT-VAL
DISPLAY 'OUT VALX: ' WS-OUT-VAL-X
OPEN OUTPUT OFILE
IF NOT OFILE-STAT-OK THEN
DISPLAY "OFILE OPEN STATUS: " OFILE-STAT
STOP RUN
END-IF
INITIALIZE OFILE-REC
MOVE WS-OUT-VAL TO COMP3-NBR
WRITE OFILE-REC
IF NOT OFILE-STAT-OK THEN
DISPLAY "OFILE WRITE STATUS: " OFILE-STAT
STOP RUN
END-IF
GOBACK
.
系统输出:
******************************** Top of Data ***********************************
VALUE IN: 030.006216
HOLD VAL: 030.006216
OUT VAL : 030006216
OUT VALX: : ::%
******************************* Bottom of Data ********************************
OFILE 内容以十六进制显示:
****** ***************************** Top of Data ******************************
000001 %
000260000000000000000000000000000000000000000000000000000000000000000000
3061C0000000000000000000000000000000000000000000000000000000000000000000
------------------------------------------------------------------------------
****** **************************** Bottom of Data ****************************
我觉得一切都很好!我认为您的代码中一定还有其他问题。