Converting PD to character

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 5
Accepted Solution

Converting PD to character

We've just upgraded to SAS 9.3 in out z/OS mainframe environment and code that was working without warning in 9.1 is now giving us headaches.

 

For example, two lines of code giving us fits are these:

 

(LOSCNT01-LOSCNT05) ($9. +9)
(LOSAMT01-LOSAMT05) ($9. +9)

 

We're coming from a packed decimal to a character display:  -1951     0      0      5477      14673        -16712

 

Is there now a more appropriate way to do this that will not result in a return code 4?  The results are still accurate, it's just the scheduler that has an attitude problem.

 

 

 


Accepted Solutions
Solution
‎04-19-2016 01:09 PM
Respected Advisor
Posts: 4,977

Re: Converting PD to character

OK ... assuming negative signs should be preserved, here's a recommendation.  Create new variables in the final DATA step that writes out the results.  For example, after the SET statement, add:

 

array cc {5} $ 9 CC01 - CC05;

array ca {5} $ 9 CA01 - CA05;

array loscnt {5} LOSCNT01-LOSCNT05;

array losamt {5} LOSAMT01-LOSAMT05;

do _n_=1 to 5;

   cc{_n_} = left(put(loscnt{_n_}*10, 17.));

   ca{_n_} = left(put(losamt{_n_}*100, 11.));

end;

 

The new variables should contain the strings that you would like to write out.  (You can probably test that independently of the program with a few lines of test data.)  Just use them in the PUT statement instead of the original variable names:

 

PUT ...

  
                @021 (CC01-CC05) ($9. +9)   
                @030 (CA01-CA05) ($9. +9)   

 

     ...;

 

From where I sit, I think this does it.  But give it a test drive and see if you like the results.  Good luck.

View solution in original post


All Replies
Respected Advisor
Posts: 3,063

Re: Converting PD to character

Please post the warnings and/or errors from your SAS log along with the code step causing it.

Respected Advisor
Posts: 4,977

Re: Converting PD to character

Can you supply a little more context?  Like whether the code you showed is part of a PUT statement or an INPUT statement or some other statement entirely?  And what messages you are getting in the log?

 

It's hard to envision the code you posted as being part of a problem of any sort just from upgrading the software.

Occasional Contributor
Posts: 5

Re: Converting PD to character

DATA DATA1;                                  
  INFILE OLINZIP1;                           
  INPUT  @001 ZIPCODE   $5.                  
         @006 POLTYPE   $1.                  
         @007 LOSSTYPE  1.                   
         @008 (LOSCNT01-LOSCNT05) (PD9.1 +9) 
         @020 (LOSAMT01-LOSAMT05) (PD6.2 +12)
         @099 TYPEREC   $CHAR2.              
         @101 COMPANY   $1.                  
         @102 LINE      $2.                  
       ;                                     

PROC SUMMARY;                                       
  CLASS COMPANY FMTLINE ZIPCODE POLTYPE LOSSTYPE;   
  VAR LOSCNT01-LOSCNT05 LOSAMT01-LOSAMT05;          
  ID TYPEREC;                                       
  OUTPUT OUT=DATA2 SUM=;                            


DATA DETALPL1 DETALFL1                    
     DETALPL2 DETALFL2                    
     DETALML1 DETALEL1                    
     DETALML2 DETALEL2;                   
  LENGTH CHYEAR $4 NUMYEAR 4;             
  SET DATA2;                              
  IF _TYPE_ = '11111'B THEN               
    DO;                                   
      CHYEAR = "&ACCTCCYY";               
      NUMYEAR = CHYEAR;                   
      LOSCNT = SUM(OF LOSCNT01-LOSCNT05); 
      LOSAMT = SUM(OF LOSAMT01-LOSAMT05); 

LABEL                           
    POLTYPE  = 'POL.\TYPE'      
    LOSSTYPE = 'LOSS\TYPE'      
    LOSCNT01 = 'RANGE 1\  COUNT'
    LOSAMT01 = 'RANGE 1\ AMOUNT'
   LOSCNT02 = 'RANGE 2\  COUNT'   
   LOSAMT02 = 'RANGE 2\ AMOUNT'   
   LOSCNT03 = 'RANGE 3\  COUNT'   
   LOSAMT03 = 'RANGE 3\ AMOUNT'   
   LOSCNT04 = 'RANGE 4\  COUNT'   
   LOSAMT04 = 'RANGE 4\ AMOUNT'   
   LOSCNT05 = 'RANGE 5\  COUNT'   
   LOSAMT05 = 'RANGE 5\ AMOUNT'   
   LOSCNT   = '  TOTAL\  COUNT'   
   LOSAMT   = '  TOTAL\ AMOUNT'   
   ;                              

DATA _NULL_;   
  SET DETALPL1 
      DETALFL1 
      DETALML1 
      DETALEL1 
      DETALPL2 
      DETALFL2 
      DETALML2 
      DETALEL2;

   FILE OLMOZIP1 LRECL=112;                   
       PUT  @001 NAICGRP   Z4.                  
                @005 NAICCONM  Z5.                  
                @010 NUMYEAR   Z4.                  
                @014 ZIPCODE   $5.                  
                @019 POLTYPE   $1.                  
                @020 LOSSTYPE  Z1.                  
                @021 (LOSCNT01-LOSCNT05) ($9. +9)   
                @030 (LOSAMT01-LOSAMT05) ($9. +9)   
WARNING: Variable LOSCNT01 has already been defined as numeric. 
WARNING: Variable LOSCNT02 has already been defined as numeric. 
WARNING: Variable LOSCNT03 has already been defined as numeric. 
WARNING: Variable LOSCNT04 has already been defined as numeric. 
WARNING: Variable LOSCNT05 has already been defined as numeric. 
375                   @111 TYPEREC   $2.;                       
WARNING: Variable LOSAMT01 has already been defined as numeric. 
WARNING: Variable LOSAMT02 has already been defined as numeric. 
WARNING: Variable LOSAMT03 has already been defined as numeric. 
WARNING: Variable LOSAMT04 has already been defined as numeric. 
WARNING: Variable LOSAMT05 has already been defined as numeric. 
Respected Advisor
Posts: 4,977

Re: Converting PD to character

The messages help a lot.  But there is also a question of what you would like the result to be.

 

The program intends to write back out your original variables (LOSCNT01-LOSCNT05 and LOSAMT01-LOSAMT05).  But what form should be used for writing them to OLMOZIP1?  Should they be written back in their original packed decimal form?  Or should they be written as numerics?

 

In any case, it's good that you upgraded the software and got these messages.  The program was never producing the correct answer as output even using the older release of the software.  It is conceivable that some option setting changed with the new release, triggering the warning message.  But it's time to understand the output that you would like and fix the program so it produces that output.

Occasional Contributor
Posts: 5

Re: Converting PD to character

The file created displays the packed numeric fields as zero-suppressed characters:  exactly the output one would get from a COBOL report when PIC ZZZZZZZZ9 was used:

 

012323361201563069E2        0        0        0        0        1     2075      0        0        0        0

 

Perhaps the report should be converted to COBOL so it can be understood.  Our SAS expertise has pretty much retired.

Respected Advisor
Posts: 4,977

Re: Converting PD to character

I'm afraid my COBOL knowledge withered on the vine decades ago.  Let's take a sample case.  Let's say LOSAMT01 originally contains the 12 hex characters:

 

12345678901D

 

What are the hex characters that should be used to express LOSAMT01 in the output file?

Occasional Contributor
Posts: 5

Re: Converting PD to character

[ Edited ]

Oh, you heathen!  To not know the language of the Gods!  :-D

 

The field is limited to 9 characters, so in this example, I would expect to see "-345678901" (high orders truncated).

 

Using a smaller example of "123456D", I would expect "-123456".  Likewise, "123456C" would be "123456".

 

Basically, the leading zeroes suppressed with the negative sign, when necessary.

 

 

Respected Advisor
Posts: 4,977

Re: Converting PD to character

Guilty as charged.

 

Just to clarify, though, when SAS reads the value it is inserting a decimal point.  Starting with:

 

0123456D

 

The value that SAS gets would be -1234.56

 

Also note, it takes 10 characters to write out -345678901

 

So does this become -45678901 or does the negative sign get removed?

Occasional Contributor
Posts: 5

Re: Converting PD to character

I'm not sure if we are just dropping the decimals or ignoring the decimal points.  All the output is interger:  no decimals, no tenths or hundredths.  I really don't understand the exact working of the ($9 +9) instruction (parameter?  informant?).

 

And of course, SAS has no debug so you can see what is actually happening instruction by instruction.  (boo-hoo)

 

The display fields are exactly 9 columns each, so I'm not sure what happens to a 9-digit number with a negative sign.  So far, that hasn't been encountered in the datasets I've been reviewing.

Solution
‎04-19-2016 01:09 PM
Respected Advisor
Posts: 4,977

Re: Converting PD to character

OK ... assuming negative signs should be preserved, here's a recommendation.  Create new variables in the final DATA step that writes out the results.  For example, after the SET statement, add:

 

array cc {5} $ 9 CC01 - CC05;

array ca {5} $ 9 CA01 - CA05;

array loscnt {5} LOSCNT01-LOSCNT05;

array losamt {5} LOSAMT01-LOSAMT05;

do _n_=1 to 5;

   cc{_n_} = left(put(loscnt{_n_}*10, 17.));

   ca{_n_} = left(put(losamt{_n_}*100, 11.));

end;

 

The new variables should contain the strings that you would like to write out.  (You can probably test that independently of the program with a few lines of test data.)  Just use them in the PUT statement instead of the original variable names:

 

PUT ...

  
                @021 (CC01-CC05) ($9. +9)   
                @030 (CA01-CA05) ($9. +9)   

 

     ...;

 

From where I sit, I think this does it.  But give it a test drive and see if you like the results.  Good luck.

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 10 replies
  • 502 views
  • 1 like
  • 3 in conversation