Decode a Binary Coded Decimal

99封情书 提交于 2019-12-13 05:13:55

问题


I have a field pic X(03) with a date in it as X'160101' format yymmdd.

I will like to know how to convert it to pic x(06).

So far I tried to move it back to a 9(03) comp and move the 9(03) comp to a 9(06) but it didn't work.

How can I do this?


回答1:


If you search stackoverflow, you should find the answer (this has already been answered).

But Create a fields like (my-date-x holds the date):

   03  my-date-x            pic x(3).
   03  my-date-9            pic 9(6).

   03  date-ymdv0           pic 9(6)v9 comp-3.
   03  date-x               pic x(3) redefines date-ymdv0.

And the code is

   Move 0                   to date-ymdv0 
   Move my-date-x           to date-x
   Move date-ymdv0          to my-date-9

The reason it works is for 9(6)v9 comp3 160101 is stored as x'1601010c' which is what you have (+ a 0c at the end).




回答2:


What you have is a Binary Coded Decimal (BCD). That is, the data is held in a binary field, but it is the decimal representation, not the binary, which is important for the value. X'160101' in would be 1,442,049. X'160201' would be 1,442,305. So if you were able to treat it as a binary field (you'd have to prepend a binary zero to make it the correct length for a binary field) you'd have to do some silly calculation.

So you do something different, and easier. BCD is not a native COBOL datatype. PACKED-DECIMAL (often the same as COMP-3/COMPUTATIONAL-3) is a BCD-type which includes a sign-value in the low-order (right-most) half-byte. So not quite a BCD, but you can treat your BCD as PACKED-DECIMAL like this:

01  BCD-TO-PACKED.
    05  BTP-SOURCE-BCD                  PIC XXX.
    05  BTP-PACKED-ZERO  PACKED-DECIMAL PIC 9 VALUE ZERO.
01  FILLER 
    REDEFINES BCD-TO-PACKED.
    05  BTP-PACKED-TO-MOVE
                         PAKCED-DECIMAL PIC 9(6)V9.

01  DATE-AS-PIC-X                       PIC X(6).
01  DATA-AS-CHARACTER-NUMERIC
    REDEFINES DATE-AS-PIC-X             PIC 9(6).


    MOVE your-source-value       TO BTP-SOURCE-BCD
    MOVE BTP-PACKED-TO-MOVE      TO DATA-AS-CHARACTER-NUMERIC

After that you can happily reference DATE-AS-PIC-X to do whatever you want with it.

BCD-TO-PACKED is a four-byte group field which, through the VALUE clause and through nothing ever changing, has, in the last by X'0F'. That's an unsigned packed-decimal field with one digit and a value of zero.

Then you do the X-to-X MOVE for BTP-SOURCE-BCD. BCD-TO-PACKED now looks like this: X'1601010F'. Which is perfectly valid for a packed-decimal field. You could divide that by 10 to get your date (REDEFINES it as PACKED-DECIMAL PIC 9(7)) but why waste CPU?

Instead, in the REDEFINES you define one decimal place (V9). When the compiler generates the code to MOVE that to another numeric field with no decimal places, the source decimal place(s) are just dropped off. Presto! Divide by 10 without dividing.

Note: The data-names chosen are to aid the explanation. You should make yours meaningful to the data, not just use "trite" names. "Character numeric" is called USAGE DISPLAY in COBOL, it is the default if a USAGE is not supplied. The word USAGE is rarely used itself. So USAGE DISPLAY is what you have when there is a PIC X or PIC 9 field with no other usage.

Note: You should probably not be using two-digit years. You won't be able to deal with dates earlier than 2000 or later than 2199. Historical use of two-digit years was due to expensive disk storage and "data redundancy" (all century values were 19, so why hold the value 19 80 different times for the same account). If using two-digit years, ensure that there is something somewhere which is relevant to the century.

Note: If you attempt to MOVE a PIC X field to a numeric field, the compiler will assume that you have valid character numbers in the field, which is one reason your original attempt failed.



来源:https://stackoverflow.com/questions/37058303/decode-a-binary-coded-decimal

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!