IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

Moving of value from 9(10) to 9(10)


IBM Mainframe Forums -> COBOL Programming
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
praveensn

New User


Joined: 30 Jul 2008
Posts: 32
Location: Pune

PostPosted: Thu Jul 14, 2011 3:02 pm
Reply with quote

Hi,

I have a query on moving a numeric variable to numeric variable.

The query is:

I am reading a 9(10) value from an Input file and moving it to working storage variable 9(10).

If the value of Input file is '0012345492' then correct value is moved to working storage variable.i,e '0012345492'.

But,If the last value is space,for example '002345123 ' then zero (0) is moved to the last field in working storage variable.The output will be '0023451230'.

But this does not happen,if the space is in between the fields.

For example.
The Input value is '03 456782',then the output will be same as Input '03 456782'.

Also,both fields are just 9(10) and they are not comp values.

We gave one more try,as moving 'ABCDEF345A' then the output would be
'ABCDEF3451'

where the last byte is getting converted to Hex.

The problem is only with the last byte.

I hope you understand my query.

Regards,
Praveen
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Jul 14, 2011 3:17 pm
Reply with quote

when using display numerics, always IF NUMERIC. if not numeric,
then do not deal with the data, post it as non-numeric and move on.

display numeric is nearly the same as pic x. go thru the numerous posts in this forum concerning the oddities of moving garbage to garbage and anticipating the outcome.
Back to top
View user's profile Send private message
praveensn

New User


Joined: 30 Jul 2008
Posts: 32
Location: Pune

PostPosted: Thu Jul 14, 2011 3:31 pm
Reply with quote

Hi,

I am checking the condition as IF Numeric and IF Not Numeric,but the problem arises before this.

I am straight away reading a variable of 9(10) and and moving it to an working storage variable of 9(10).

The problem is,when the last byte is space,say for example '003902123 ' then numeric zero is moved to last byte as''0039021230',but if the space is in between as '00390 230' then same value is moved as '00390 230'.

Regards,
Praveen.
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Jul 14, 2011 3:45 pm
Reply with quote

well, make the IF NUMERIC check immediately after reading the variable and before moving it.

as i said, DISPLAY numeric will allow garbage-in to be moved.
Back to top
View user's profile Send private message
Nic Clouston

Global Moderator


Joined: 10 May 2007
Posts: 2455
Location: Hampshire, UK

PostPosted: Thu Jul 14, 2011 3:47 pm
Reply with quote

it is NOT 9(10) if it contains non-digits. Get your input fixed. AND do as Dick has suggested.
Back to top
View user's profile Send private message
praveensn

New User


Joined: 30 Jul 2008
Posts: 32
Location: Pune

PostPosted: Thu Jul 14, 2011 4:24 pm
Reply with quote

Hi,

I hope you are not clear with my query.

I have tried with your Inputs,but I am not expecting that.

My Input is of 10 bytes numeric field as'0034212343' and,If I move it to a working storage variable of 10 bytes numeric field,it should move and it gets moved as well.

But,if the last byte in this is space,as '009909032 'then 0 is moving in to that field,then I am getting output as '0099090320',where my expected output is '009909032 '.

But,if the space is in between the variables as '093 9453 2' then the same value is moving, as it is ''093 9453 2'. Space is not replaced by zeros.

Only if the last byte is space then zero is replaced by it, and not in any other fields.

Regards,
Praveen.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Jul 14, 2011 4:32 pm
Reply with quote

You have a data item which is supposed to be numeric. You have the potential for getting assorted rubbish in it.

As dbz has said, the first thing after reading your input, check all your numeric fields for being "numeric". If any are not numeric, then the record as a whole should be processed as a rejection.

Why you test it for numeric is to stop rubbish getting into your system. To have a look at how bad it might be, use one of your receiving data items in some sort of calculation. It will work. Even with all the letters.

Again, as dbz has said, search the forum for further discussions about this.

What I would do, as we can tell you have NUMPROC(NOPFD), is redefine your input data item as PIC X(10) and test that. You might (I do not know, unless you generate the pseudo-assembler and post it) have a problem otherwise with your single rightmost space example.

Read all the stuff. If you still don't understand what is happening, ask again.

Also, try to find out what Hexadecimal means. Try to find out what a "field" is and what a "byte" is.
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Jul 14, 2011 4:47 pm
Reply with quote

Quote:
But,if the last byte in this is space,as '009909032 'then 0 is moving in to that field,then I am getting output as '0099090320',where my expected output is '009909032 '.

that is why NUMVAL from a PIC X(10) field is to be used.

Quote:
But,if the space is in between the variables as '093 9453 2' then the same value is moving, as it is ''093 9453 2'. Space is not replaced by zeros.


do you have 3 different numeric values or one?

possibly:
redefine you input as PIC X(10).
INSPECT pic-x-for-10-input REPLACING SPACE BY ZERO.

Then do your move.
====================================
but of course, the INSPECT will invalidate your first situation.

you are proposing two difference rules for the same field.

decide what you want. if you want to replace intervening spaces with zeros, yet not replace the last (10th char) with zero if space,
then only convert the first 9 char and then do NUMVAL.
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8696
Location: Dubuque, Iowa, USA

PostPosted: Thu Jul 14, 2011 4:53 pm
Reply with quote

Praveen, what you are describing is normal and expected behavior for COBOL. A numeric USAGE DISPLAY variable, contrary to the beliefs of many new to COBOL, can actually contain letters, special characters, spaces -- lots of non-numeric things. If you attempt to do arithemtic on such a variable, you may -- but not always, depending upon the actual data in the variable -- get a S0C7 abend, but merely having non-numeric data in the variable is not impossible under the rules of COBOL. When you move the variable to another numeric USAGE DISPLAY variable, COBOL ensures that the value is unsigned. How does it do this? For a USAGE DISLAY variable, the zone bits of the last byte are forced to be X'F'. Since a space is X'40', chaniging the zone to X'F' from X'4' means the value becomes X'F0' -- which is a numeric zero in EBCDIC. COBOL only does this for the LAST byte, hence the behavior you described.

A priofessional COBOL programmer always checks the data -- if it is a numeric variable, use the IF NUMERIC test before doing ANYTHING with that variable. This will prevent production abends (which usually occur at 3 AM), but does require some forethought about what to do in the case of invalid data for each varaible.
Back to top
View user's profile Send private message
Marso

REXX Moderator


Joined: 13 Mar 2006
Posts: 1353
Location: Israel

PostPosted: Thu Jul 14, 2011 5:21 pm
Reply with quote

Just in case you need more information, read this: ibmmainframes.com/viewtopic.php?t=55189

praveensn wrote:
I hope you are not clear with my query.
icon_exclaim.gif
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Fri Jul 15, 2011 5:29 am
Reply with quote

Marso wrote:
[...]
praveensn wrote:
I hope you are not clear with my query.
icon_exclaim.gif


Maybe it means "I didn't get the answer I wanted, so I hope that you have misunderstood my question"?

Code:
01  W-NUMBER-FIELD-EXAMPLE-1 PIC 9(03).
01  W-NUMBER-FIELD-EXAMPLE-2 PIC S9(03).


The above definitions allocate storage in your Cobol program. With no explicit USAGE, they are USAGE DISPLAY by default. The storage allocated for each is three bytes. The compiler (clever little beast that it is) remembers this sort of stuff so that it later knows what instructions to generate when/if you want to do something with these in the Procedure Division.

Each of the three bytes in each of the two fields can contain any value from 0 to 255, as each byte is 8 bits and 11111111 is binary for 255 (and 0 is binary for zero). This is also true for every single byte of storage you define in your Cobol program.

They can contain any value, but often there are conventions for what they can validly contain.

The convention for DISPLAY NUMERIC is as follows. Note, hexadecimal notation is used below.

The rightmost byte is considered as two half-bytes. The left half-byte (or nybble (I guess a "nibble" is smaller than a "bite", so a "nybble" is smaller than a "byte")) contains the code for the sign. C here means positive, D means negative, F means "unsigned" and is treated as positive. A, B and E can also be valid (the first group are called "preferred signs" by IBM, and this group are called "non-preferred signs") but let's try to leave that aside.

The right nybble of the sign byte contains the rightmost numeric digit of the field.

All the leftmost bytes are considered as two half-bytes. The left nybble of each is called the "zone" and has the value of F. The right nybble of each contains the remaining digits of the number. To "read" a DISPLAY numeric (for instance in a dump) look at all the rightmost nybbles from left to right, gives you the number. Left nybble of rightmost byte gives you the sign. All the other left nybbles should contain F.

Remember that this is a convention for what constitutes a valid DISPLAY numeric (also known as Zoned Decimal). The bytes can actually contain anything, 0-255.

To find out if the field contains valid numeric data, you have the NUMERIC class test. This will test whether the values currently in the field conform to the convention. If so, the test will be true, otherwise false.

The reason that you use the numeric test is to prevent rubbish getting into your system. Because, unless you are careful, it can.

Code:
C1C2C3 is hex for ABC. This fails the NUMERIC test.
F1F2F3 is hex for 123. This satisfies the NUMERIC test.


However, if you add one to EXAMPLE-1 while it contains ABC a "strange" thing happens. You get 124. If you add one to EXAMPLE-1 while it contains 123, a completely normal thing happens. You get 124.

Now you can't so easily tell that you have rubbish in your system, but you do.

So, what you have to do, for all new inputs into your system (ie for data that you do not already hold as valid - can be an external file, screen input, parm statement, another system in your site, etc) is TEST FOR NUMERIC and KNOW WHAT TO DO IF NOT as the very first thing you do with that "numeric" data.

Code:
4040F1 is blank blank 1
F140F1 is 1 blank 1
F1F140 is 1 1 blank


What happens if you similarly add one to these (using compiler option NUMPROC(NOPFD), the default)? You get 002, 102 and 111. Exactly what you'd get if you started with 001, 101 and 110.

You thought you'd get S0C7 if the data in a calculation was invalid? You do, but this is not "invalid" for calculation.

For DISPLAY numerics in calculations, Cobol is going to convert the Zoned Decimal format to Packed Decimal format. This is irrespective of what the field actually contains at the time.

Cobol does this by: throwing away all the zones; taking all the "numerics" for the number; using the sign to provide the sign for the packed field.

If you do this for the above examples

Code:
C1C2C3 goes to 123C (valid packed decimal)
F1F2F3 goes to 123F (valid)
4040F1 goes to 001F (valid)
F140F1 goes to 101F (valid)
F1F140 goes to 1104 (invalid - but NUMPROC(NOPFD) ensures your sign is always F for an unsigned field, so actually goes to 110F with EXAMPLE-1, so valid)


If you want to get a S0C7 with EXAMPLE-1, you have to get a non-letter in the sign (which NOPFD will not allow) or a non-digit in any of the right nybbles.

If you fill a numeric field with periods/full-stops, you will get the S0C7.

So, a DISPLAY numeric, like any other field, can contain "anything". A sub-set of "anything" will allow manipulation of the field without an abend. A sub-set of that sub-set conforms to the convention for representing DISPLAY numeric/Zoned Decimal fields.

If you want to prevent your system potentially becoming screwed, use the NUMERIC test on all new "numeric" input before you do anything else with it. Do something reasonable if not numeric (don't just ignore it and hope no-one notices).

What I don't know for sure is this. Do you have to test a PIC X(nn) instead of a PIC 9(nn) when using NUMPROC(NOPFD)?

For almost all references to a numeric item, NUMPROC(NOPFD) will ensure a valid sign every time the item is referenced. I suspect that for the NUMERIC test it does not do this, but I do not know. If someone wants to generate the code and let us know, or post the generated code, they are more than welcome.

For anyone who is trying to get to grips with the above for the first time, try to find time to work through the above values with the EXAMPLE-2 field, so you can see any differences. Do it with your default NUMPROC setting, and also with the other NUMPROC setting (ignore MIG unless you are using it).

Also, for fun, set the field to space, each of the three bytes. Try to test with Cobol code whether the field is space.

Code:
IF W-NUMBER-FIELD-EXAMPLE-1 EQUAL TO SPACE
    everything is fine
ELSE
    something strange
END-IF


If something strange happened, try to find out how to prevent it, by consulting the manuals. If everything was fine, try with NUMPROC(NOPFD).
Back to top
View user's profile Send private message
Bill O'Boyle

CICS Moderator


Joined: 14 Jan 2008
Posts: 2501
Location: Atlanta, Georgia, USA

PostPosted: Fri Jul 15, 2011 6:22 am
Reply with quote

Bill,

Here are some NUMERIC oddities -

If you have a signed packed-decimal field and for some reason, the sign-nibble is a X'F' it will fail the NUMERIC test.

If you have an unsigned packed-decimal field and it has a valid sign-nibble of other than X'F' it will fail the NUMERIC test.

The same holds true for signed and unsigned display-numeric.

COBOL still uses Translate Tables via TRT instructions and this is the reason for the failure for packed-decimal and display-numeric when the signs don't match the picture.

It's too bad that the newer COBOL compiler's haven't adapted the TP (Test Decimal) instruction, which eliminates TRT's for packed-decimal numeric validation (as well as the Translate Tables) and recognizes all valid sign-nibbles.

As far as display-numeric, I believe COBOL still uses TRT's with Translate Tables as there doesn't seem to be an equivilent instruction like TP for display-numeric.

Bill
Back to top
View user's profile Send private message
dick scherrer

Moderator Emeritus


Joined: 23 Nov 2006
Posts: 19244
Location: Inside the Matrix

PostPosted: Fri Jul 15, 2011 7:31 am
Reply with quote

Hello,

In our forums, "I hope" very often means "I believe" or "I understand". Or even the stronger "I know".

fwiw,

d
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sat Jul 16, 2011 6:33 am
Reply with quote

Bill O'Boyle wrote:
Bill,

Here are some NUMERIC oddities -

If you have a signed packed-decimal field and for some reason, the sign-nibble is a X'F' it will fail the NUMERIC test.

If you have an unsigned packed-decimal field and it has a valid sign-nibble of other than X'F' it will fail the NUMERIC test.

The same holds true for signed and unsigned display-numeric.

COBOL still uses Translate Tables via TRT instructions and this is the reason for the failure for packed-decimal and display-numeric when the signs don't match the picture.

It's too bad that the newer COBOL compiler's haven't adapted the TP (Test Decimal) instruction, which eliminates TRT's for packed-decimal numeric validation (as well as the Translate Tables) and recognizes all valid sign-nibbles.

As far as display-numeric, I believe COBOL still uses TRT's with Translate Tables as there doesn't seem to be an equivilent instruction like TP for display-numeric.

Bill


Bill,

NUMCLS already influences the sign in a numeric test. I think you can get the other sign values to test as numeric when NUMCLS is set for that.

My approach to the data is, if it fits the PICTURE it is OK, else it is not. For me, this includes the contents of the "sign".

If I request unsigned numerics in a spec to an external system, then they don't get sign-off if they try to give me signed numerics. Vice versa. Packed or unpacked.

Code:
01  W-NUMBER-FIELD-EXAMPLE-1 PIC 9(03).
01  W-NUMBER-FIELD-EXAMPLE-2 PIC S9(03).


Take '12C' as the value in each of the above. In the first, I'd want it to be not numeric. In the second I'd want it to be numeric.

Take '123' as the value in each of the above. In the first, I'd want it to be numeric. In the second I'd want it to be not numeric.

To me that is correct, and I'd get worried if that were allowed to slip. OK, I'd work somewhere that operated like that, but I'd worry away to myself.

For instance, I'm entering a PARM value, 12345. I "fat-finger" it to 1234t. I do a numeric check on the extracted parm in the program. I don't want my erroneous "12343" to be processed, so I hope the numeric test fails.

We quickly get to the NUMPROC thing again.

NUMPROC(PFD) if your numeric data conforms to the PICTURE, else NUMPROC(NOPFD).

OK, I'm a tough guy, my numeric data on my systems conforms to the PICTURE. But then I'd have to sit hard on everyone else doing any work receiving (or sending) external data. Test cases. OK, not too bad.

Then there's NOPFD. Less worry about the "logic" not working as expected, sign-fixing on every reference to every numeric item (nearly). 24/7/365. Imagine someone defines Agent Number as 10 bytes numeric (like they thought one day they might like to use it in a COMPUTE). I reference Agent Number 10 times on average per program. Say 100 programs (keep the math simple). Rats, forgot about the 7/365 bit. Say 10,000 records on the file. That is a lot of worthless sign-fixing per year. And I've got another 100 items like the Agent Number. Sheesh.

I think I'd be happier if a NUMPROC(CLASSIC) was available. I haven't checked how well MIG fits that bill.

Bill
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> COBOL Programming

 


Similar Topics
Topic Forum Replies
No new posts Moving Or setting POINTER to another ... COBOL Programming 2
No new posts Moving a COMP-3 Variable to a Numeric... COBOL Programming 2
No new posts Moving a PS file as body of a mail! JCL & VSAM 4
No new posts Moving UDB database to Db2 on z/OS DB2 4
No new posts Moving values to a variable of copybo... COBOL Programming 6
Search our Forums:

Back to Top