COBOL DATATYPE CONVERSION: Конвертировать дату в DDMMYY в упакованный десятичный код из 3 байтов
У меня есть требование, где я хочу переместить дату (DDMMYY) в числовом формате в упакованный десятичный / comp-3 из 3 байтов. дата должна быть перемещена в файл, где для нее выделено только 3 символа / байта. Это то, что я пытался.
03 WD-DDMMYY-DT-NUMERIC PIC 9(06).
03 WD-DDMMYY-DT-COMP3 PIC S9(06) COMP-3.
03 WD-DDMMYY-REDF REDEFINES WD-DDMMYY-DT-COMP3.
05 WD-3CHARS-DT-COMP3 PIC X(03).
05 FILLER PIC X(01).
Move WD-DDMMYY-DT-NUMERIC to WD-DDMMYY-DT-COMP3
Move WD-3CHARS-DT-COMP3 to file-variable --> X(03)
Я не получаю желаемое значение в выводе. как это можно сделать?
3 ответа
Ответ посчетам правильный, но я постараюсь дать более наглядный ответ, используя дату 150131 (31 января 2015 г.)
если вы объявите поле как
05 WD-DDMMYY-DT-NUMERIC PIC 9(06) comp-3.
затем 150131 сохраняется в WD-DDMMYY-DT-NUMERIC как x'01 50 13 1c', который занимает 4 байта. Но если вы объявите поле как
05 WD-DDMMYY-DT-NUMERIC PIC 9(06)V9 comp-3.
05 FILLER REDEFINES WD-DDMMYY-DT-PD.
10 WD-BCD PIC X(03).
затем 150131 сохраняется в WD-DDMMYY-DT-NUMERIC как x'15 01 31 0c', который снова занимает 4 байта, но WD-BCD содержит x'15 01 31', который содержит всю дату, и имеет длину 3 байта
Вы также захотите "распаковать" вашу дату позже в другой программе, поэтому используйте REDEFINES, а не группу с подчиненным упакованным десятичным числом:
05 WD-DDMMYY-DT-NUMERIC PIC 9(06).
05 WD-DDMMYY-DT-PD PACKED-DECIMAL PIC 9(06)V9
VALUE ZERO.
05 FILLER
REDEFINES
WD-DDMMYY-DT-PD.
10 WD-BCD PIC X(03).
10 FILLER PIC X.
MOVE WD-DDMMYY-DT-NUMERIC TO WD-DDMMYY-DT-PD
MOVE WD-BCD TO wherever-you-want
Полубайт младшего разряда (nybble) поля упакованного десятичного числа указывает операционный знак (C для положительного, D для отрицательного, F для без операционного знака, рассматриваемый как положительный - есть также некоторые Непреференциальные знаки, A, Б, д).
Для части цифр упакованного десятичного числа одна цифра занимает один кусочек.
Для упакованного десятичного числа любое заданное число байтов позволит точно соответствовать нечетному числу цифр. Четному количеству цифр всегда должен предшествовать ноль (вам не стоит об этом беспокоиться, компилятор сделает это за вас).
Чтобы получить шесть десятичных цифр, "упакованных" в три байта, вы должны игнорировать знак (помня, что nybble используется даже для поля без знака). Этот результат является соглашением, которое называется Binary Coded Decimal (BCD). COBOL не имеет встроенной поддержки BCD, поэтому вам придется кодировать. Но не много.
Чтобы убрать знак с дороги, вам нужно сдвинуть цифры влево на один клочок, оставив знак там, где он есть. Оставить знак в покое не проблема, COBOL сделает это за вас. Сдвиг влево подобен умножению на степень 10. Чтобы сдвинуть влево, умножьте на 10.
Тем не менее, существует более точный способ организовать сдвиг, который состоит в том, чтобы определить упакованное десятичное поле, чтобы иметь одно десятичное место (V9). Когда ваша дата, очевидно, целое число, перемещается в это поле, десятичная часть будет равна нулю (одна цифра), а дата даты будет предшествовать нулю.
Стоит отметить, что в IBM Enterprise COBOL V5 любое умножение или деление на степень 10 фактически реализуется как соответствующий сдвиг.
Это будет означать, что код, сгенерированный компилятором V5, будет очень похож на MULTIPLY на 10 и MOVE на поле с одним десятичным знаком. Возможно идентично (я не могу проверить).
Чтобы "распаковать" дату:
05 WD-DDMMYY-DT-NUMERIC PIC 9(06).
05 WD-DDMMYY-DT-PD PACKED-DECIMAL PIC 9(06)V9
VALUE ZERO.
05 FILLER
REDEFINES
WD-DDMMYY-DT-PD.
10 WD-BCD PIC X(03).
10 FILLER PIC X.
MOVE wherever-you-want TO WD-BCD
MOVE WD-DDMMYY-DT-PD TO WD-DDMMYY-DT-NUMERIC
Обратите внимание на ЗНАЧЕНИЕ ЗНАЧЕНИЯ в этом определении. Так работает Enterprise COBOL (в любом случае, до V4.2), в действительности это не нужно, но это документально для программиста. Байт младшего разряда (четвертый) никогда не изменяется от своего начального значения, то есть он всегда содержит X'0F'. Компилятор на самом деле "закорачивает" это, потому что он все равно заставит вывод быть неподписанным, поэтому ему не нужен знак из поля источника.
01 WORKING-VARIABLES.
03 WD-DDMMYY-DT-NUMERIC PIC 9(06).
03 WD-3CHARS-DT-COMP3-X.
05 WD-DDMMYY-DT-COMP3 PIC 9(08) COMP-3.
03 FILLER REDEFINES WD-3CHARS-DT-COMP3-X.
05 FILLER PIC X(01).
05 WD-3CHARS-DT-COMP3 PIC X(03).
MOVE 311216 TO WD-DDMMYY-DT-NUMERIC.
MULTIPLY WD-DDMMYY-DT-NUMERIC
BY 10 GIVING WD-DDMMYY-DT-COMP3.
Move WD-3CHARS-DT-COMP3 to FILE-O-FIELD.
должен решить вашу проблему.