Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Difficult recognizable tricks in COBOL 11

Status
Not open for further replies.

Crox

Programmer
Apr 3, 2000
893
NL
I am looking for tricks in COBOL. I need examples of code that is doing something else then you think at first sight.

Thanks in advance!

Regards,

Crox
 
Bill,

You're right.

I was concentrating on the trick part - where you throw together some weird looking code and you consistently obtain predicted results.

In the case of the two "tricks" I am ranting about, those are usually considered hard to find bugs: they look normal (at first), while giving inaccurate results. Because the results are bad, I find it hard to call them tricks. A good trick should 'pull the rabbit from the hat', I like to think.

Dimandja
 
Using an unsigned numeric field is not a buG. It is fully documented COBOL standard and is very useful. Many languages have an ABS() function. COBOL does not, but assigning a result to an unsigned field accomplishes the same thing but more efficiently, and it is fully documented.

In a language with ABS(), it would not be considered a bug to write
TOGGLE = ABS(TOGGLE - 1)
 
It is not the feature that is the trick, it is the unusual usage thereof.
 
Ok. I'll go with that.

I wish you had made it clear at posting, though. Because, since it was obvious, to me at least, what was taking place (unsigned numeric, et al), I failed to detect the clever part of it.

I'll buy the trick.
 
Hi Crox,


Here's a mainframe COBOL entry. The data names will give away the mystery of the code's purpose. Don't know where (or if) it fits the category, but here goes:

FLIPONE.....
Code:
01  WS-WORK-AREAS.
    05  BIT-NBR                 PIC  9(04) COMP.
    05  BIT-FLIPPER             PIC  9(04) COMP VALUE 0.

    05  FLD-1.
        10  1ST-CHK-BYTE        PIC  X(01).
            88  CHK-BIT-IS-ON   VALUE X'80' THRU X'FF'.
            88  CHK-BIT-IS-OFF  VALUE X'00' THRU X'7F'.
        10  FILLER              PIC  X(01).
    05  CHK-BITS                REDEFINES
        FLD-1                   PIC  9(04) COMP.

    05  CHG-BITS                PIC  9(04) COMP.

    05  BIT-SHIFT-VALUES.
        10  BIT-1               PIC  9(04) COMP VALUE   1.
        10  BIT-2               PIC  9(04) COMP VALUE   2.
        10  BIT-3               PIC  9(04) COMP VALUE   4.
        10  BIT-4               PIC  9(04) COMP VALUE   8.
        10  BIT-5               PIC  9(04) COMP VALUE  16.
        10  BIT-6               PIC  9(04) COMP VALUE  32.
        10  BIT-7               PIC  9(04) COMP VALUE  64.
        10  BIT-8               PIC  9(04) COMP VALUE 128.
    05  BIT-SHIFT-TBL           REDEFINES
        BIT-SHIFT-VALUES.
        10  SHIFT-ENT           PIC  9(04) COMP
                                OCCURS 8.


    MOVE     your data  TO CHK-BITS(1:1)
                           CHG-BITS(1:1)
    MOVE     bit nbr    TO BIT-NBR
    MOVE     ZEROS      TO BIT-FLIPPER
    MOVE     X'80'      TO BIT-FLIPPER(1:1)
    COMPUTE  CHK-BITS    = CHK-BITS    * SHIFT-ENT(BIT-NBR)
    COMPUTE  BIT-FLIPPER = BIT-FLIPPER / SHIFT-ENT(BIT-NBR)

    EVALUATE TRUE
    WHEN CHK-BIT-IS-ON
         SUBTRACT BIT-FLIPPER FROM CHG-BITS
    WHEN CHK-BIT-IS-OFF
         ADD BIT-FLIPPER        TO CHG-BITS
    WHEN OTHER
         DISPLAY 'HOUSTON WE HAVE A PROBLEM'
         STOP RUN
    END-EVALUATE 
    MOVE CHG-BITS(1:1)  TO your receiving area
    .
FLIPALL.....

Code:
01  WS-WORK-AREAS.
    05  FLD-1.
        10  1ST-CHK-BYTE        PIC  X(01).
            88  CHK-BIT-IS-ON   VALUE X'80' THRU X'FF'.
            88  CHK-BIT-IS-OFF  VALUE X'00' THRU X'7F'.
        10  FILLER              PIC  X(07).
    05  CHK-BITS-64             REDEFINES
        FLD-1                   PIC  9(10) COMP.

    05  CHG-BITS-64             PIC  9(10) COMP.
    05  BIT-FLIPPER             PIC  9(10) COMP VALUE ZEROS.
    05  LOOP-CNTL               PIC  9(04) COMP VALUE ZEROS.
    05  BIT-LOC                 PIC  9(04) COMP VALUE ZEROS.
        88  ONE-BIT             VALUE 1 THRU 8.
        88  BIT-STRING          VALUE 0.
        88  ERROR               VALUE 9 THRU 65535.



    MOVE     your data    TO CHK-BITS-64(1:nbr of bytes)
                             CHG-BITS-64(1:nbr of bytes)
    MOVE     nbr of bits  TO LOOP-CNTL
    MOVE     ZEROS        TO BIT-FLIPPER
    MOVE     X'80'        TO BIT-FLIPPER(1:1)

    PERFORM  XXXX-CHK-A-BIT  LOOP-CNTL TIMES
    MOVE CHG-BITS-64(1:nbr of bytes)
      TO your receiving area
    .
XXXX-CHK-A-BIT.
    EVALUATE TRUE
    WHEN CHK-BIT-IS-ON
         SUBTRACT BIT-FLIPPER FROM CHG-BITS-64
    WHEN CHK-BIT-IS-OFF
         ADD BIT-FLIPPER        TO CHG-BITS-64
    WHEN OTHER
         DISPLAY 'HOUSTON WE HAVE A PROBLEM'
         STOP RUN
    END-EVALUATE
    COMPUTE  CHK-BITS-64 = CHK-BITS-64          * 2
    COMPUTE  BIT-FLIPPER = BIT-FLIPPER          / 2
    .
The later versions of IBM COBOL have callable functions that "flip" bits, but where's the fun in that? :)

Although there's nothing native to COBOL that was intended to "flip" bits, it can be accomplished with some unconventional use of binary arithmetic. Remember that multiplication/division by binary 2 is equivalent to shifting a field left/right 1 bit. Also you can turn a particular bit position in a field on or off by multiplying/dividing by the appropriate value based on the bit position. The 2 approaches proposed above take advantage of these arithmetic possibilities.

Here's an explanation of the 2 approaches:

The first (FLIPONE) will "flip" one specific bit in a specified byte. The other (FLIPALL) will scan 8 bytes of data and determine the "on/off" status of each bit in the string. In the code supplied here I've "flipped" each bit in the string. The routine can be used to selectively "flip" the bits, or, if the string represents an option list or some such, it can be used to process the options.

Because the code hasn't been tested, the usual caveats and copouts apply. I don't know how this will "wrap.

Regards, Jack.
 
(standard) COBOL is supposed (and is!) robust. Therefore I have problems finding an example that does the unexpected.
But maybe this one is a candidate:


DATA DIVISION.
WORKING-STORAGE SECTION.

01 myWorkFields.
*// COMP-1 is a small floating-point value,
*// though official COMP-1 is not standard COBOL-85.
*// For a description of a COMP-1 see link:
*// 05 theCalculatedABS COMP-1.
05 theKeyboardABS PIC 9(16).
05 theKeyboardInput PIC X(16).

PROCEDURE DIVISION.

*/**
* Purpose of this program:
*
* To accept a number from console(=keyboard)
* and return the absolute value
* without using intrinsic functions or using
* the COBOL syntactic move rules.
*
* Algoritm used:
* 1. square the input (which gives a positive result).
* 2. Take the root (which returns the absolute value
* of the original input).
*
* Note:
* The original input is limited to maximal 16 characters.
* This is done to prevent an overflow condition, even
* when this value is squared!
* Of course we test if the input is numeric (=valid) before
* we use the algoritm!
*
**/

DISPLAY 'Give a number:'
DISPLAY '(Max is : S999999999999999 (where S= + or - ))'
DISPLAY '(Or max is: 9999999999999999 ( without sign ))'

ACCEPT theKeyboardInput

IF theKeyboardInput IS NUMERIC
, PERFORM returnTheAbsoluteValue
ELSE
, DISPLAY 'invalid number!'
END-IF

GOBACK
.

returnTheAbsoluteValue.

*// first create positive number by squaring input.
COMPUTE theCalculatedABS = theKeyboardInput ** 2
*// then take the root from the square to get the
*// absolute value of the original input.
COMPUTE theCalculatedABS = theCalculatedABS ** 0.5

*// Take the absolute value (ABS) using PICture rules.
MOVE theKeyBoardInput TO theKeyboardABS

*// Compare the moved ABS value with
*// the calculated ABS value.
EVALUATE TRUE
, WHEN theKeyboadABS = theCalculatedABS
, DISPLAY 'theKeyboadABS = theCalculatedABS'
,
, WHEN theKeyboadABS > theCalculatedABS
, DISPLAY 'theKeyboadABS > theCalculatedABS'
,
, WHEN theKeyboadABS < theCalculatedABS
, DISPLAY 'theKeyboadABS < theCalculatedABS'
,
END-EVALUATE
.


Now my question is:
Can you predict which display statement is printed for a given input value prior to executing the program?
 
wahlers,

I am trying to compile your code. However, I must make changes to get it to compile: your example does not seem to have been successfully compiled. Before I mangle the code completely, could you post a cleanly compiled version?

Thanks.
 
wahlers, I have some questions with your code. I work on IBM mainframe but don't believe that there are too many differences in COBOL.

According to your DISPLAY, I can enter a number as +145. That goes into a PIC X(16) field. You then check that for NUMERIC. It will not be numeric if it has a plus sign. Only the unsigned digits 0 - 9 are allowed - in every byte. Does that mean I have to enter 16 digits all the time?

Also, your first COMPUTE is squaring the input value - PIC X(16). Can't use PIC X fields in arithmetic statements.

I assume that wasn't supposed to be part of your questions - but it doesn't appear that it will work the way you intend.
 
To COBOLKenny:

Yeh, and those are not even the only 'errors'!
You have to do some more 'field' work
E.g.:
use INSPECT statement for the sign (save the sign, the sign position and replace by space), and
use 'theKeyboardNumeric REDEFINES theKeyboardInput PIC 9(16)' for calculations (or better yet move the value to seperate, numeric, working-storage field).

You can do that yourself, I was lazy...!
It is just that it is very dangerous to use floating point fields in equality tests. That is the unpredictable part of it.


Regards, Wim.
 
You can do that yourself, I was lazy...!
You wrote it from memory without compiling? You mean this code is not guaranteed to work at all? Why post it, then? You don't have to answer that...
 
I think the last few entries are off the subject, "recognizable tricks'. I think what Crox was looking for was unusual applications of standard code that produces predictable results. Floating point on most machines is binary, but I have worked with computers that use decimal floating point, which gets rounding errors only when the number of significant digits exceeds the size of the mantisa. One such machine had no practical upper limit to the size of the mantisa.
 
To: Dimandja

I answer anyway...you are right! The question was to give code examples. At the time I only had the precision of COMP-1 (as shor float) in mind.
I don't want to dwell anymore about my code:
Either forget it or keep it in mind in the case you are ever going to use short or long float (at IBM respectively: COMP-1 and COMP-2).
(by the way: My remark about redefinition is also not complete. That is: the spaces and the sign should be replaced by zeros to make it a valid field).

To webrabbit:

In the IBM environment COMP-1 is a 4 byte floating point field and COMP-2 is an 8 byte floating point field.
Again, the COMP-x fields are non-standard an do(!) differ among the various platforms.

in the IBM environment COMP-1 defines a short floating point field. As far as I remember correctly it is defined as follows:
The first bit is the sign bit.
The next 7 bits (can address 0-127) is used for the exponent. An exponent of zero is represent by the value 64.
Any value below 64 is used for negative exponents and any value above 64 is used for positive exponents (all base 10).
The next 3 bytes are used for the mantissa.

Regards, Wim.
 
Sorry I couldn't help myself...

1. To my knowledge, according to the standard COBOL rules a display field (such as: PIC X(16)) has a valid numeric value when it contains digits only (0-9) and it may be preceded by a sign ('+' or '-'). So, yes I should have told that it was mandatory to enter 16 digits without a sign or, alternatively, 15 digits with a sign.
Any number shorter than 16 characters should have preceding zeros.
(I realise the original program example does a poor job in checking these requirements).

2. To my knowledge, according to the standard COBOL rules you can use display statements in arithmetic expressions (on the left side of '=') as long as the display variable is numeric (see 1.).

 
A PIC X field is numeric in COBOL only if each byte is a display decimal digit (0-9). No sign permitted. In the early days of IBM COBOL, an overpunch sign was permitted in the last byte, but standard COBOL now prohibits that. A display sign (+/-) has never been permitted.

In IBM mainframe floating point, the exponent is base 16: X'4212345A' = 1193050 x 162. I believe Intel floating point is the same. IBM also has 16-byte floating point as well as 8-byte (COMP-2).

The target of an arithmetic statement (left side of an "=" in a COMPUTE or after the "GIVING" in an ADD, SUBTRACT, MULTIPLY or DIVIDE) need not be numeric. The assignment rules are a bit tricky for alphanumeric targets though. It can even be Alphanumeric edited. It cannot be Alphabetic or Alphabetic Edited (the picture cannot contain any A's). Numeric Edited and Display Numeric are both valid with no special rules.

Display Numeric is always valid anywhere in an arithmetic statement. There is also Display Floating-point, which is treated syntactically as display numeric.
 
To webrabbit:

stupid me...!

I said left side...I mean the other(!) left site...thus...the right side :)
(the left site, of course, contains the numeric computed result). Sorry for this stupid mistake!
As far as I know the COMPUTE statement takes care of the calculation in intermediate result fields (which are also a potential problem for rounding, but, hey, that is an other story!).

I do not understand your floating-point comments.
Earlier I tried to tell the meaning of the IBM mainframe COMP-1 bit pattern (sign/exponent/mantissa). I am fairly sure of my explanation.
I do not understand your sentence:
In IBM mainframe floating point, the exponent is base 16: X'4212345A' = 1193050 x 16^2.

Regards, Wim.
 
The left side (not right) side of a COMPUTE statement may be numeric or numeric-edited in an ANSI/ISO conforming program ('85 Standard or later). I haven't serched yet, but I do NOT think it may be alphanumeric or alphanumeric-edited.

I don't understand the claim that you can't have a sign in a field for which IF NUMERIC class-test is performed. The following is what the '85 Standard says,

"If the data description of the item does indicate the presence of an operational sign, the item being tested is determined to be numeric only if the content is numeric and
a valid operational sign is present. Valid operational signs for data items described with the SIGN IS SEPARATE clause are the standard data format characters + and -; the implementor defines what constitutes valid sign(s) for
data items not described with the SIGN IS SEPARATE clause."

The rules in the 2002 Standard are even "loser" as they allow for IF NUMERIC tests on other USAGEs.

Bill Klein
 
I was wrong. The target of an arithmetic statement cannot be alphameric. :~/

WMK: The subject of the IF NUMERIC question is PIC X(n).

whalers: I was further explaining IBM internal floating point. The value of a floating point number would normally be stated as .mantisa x 10exponent so that +2E+123 would be equal to .123 x 102, or 12.3. But the exponent of IBM internal floating point is 16, not 10. And of course, the mantissa is binary.

BTW, my example was wrong, X'4612345A' would be 1193050. X'4212345A' would be 1193040 x 16-4, or approximately 1.820449829. :~/
 
webrabbit said:
I was wrong.

And you remain so through the rest of the post!

webrabbit said:
2E+123 would be equal to 123 x 102.
It is 2 x 10123, or 2 followed by 123 zeros.

webrabbit said:
But the exponent of IBM internal floating point is 16, not 10.
webrabbit said:
And of course, the mantissa is binary.
IBM (and some other) floating point representations use 16 as the base of the exponent portion of the represented number, and therefore also use base-16 when normalizing the represented number, placing the radix point to the left of the most significant (hexadecimal) digit of the mantissa. IBM floating point is normalized so that the most significant hexadecimal digit is nonzero; other floating point schemes normalize down to the binary digit (and some, including IEEE, even normalize off the most significant 1 bit and then assume it thereby gaining more precision), and use 2 for the exponent base.

Tom Morrison
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top