Discussion:
Converting Packed String to Zoned Decimal
(too old to reply)
Iknir
2006-09-23 15:46:18 UTC
Permalink
I have uploaded a flat file with Packed Decimal String with a length 7.
It does not unpack properly using RPG simple "MOVE" op code. However,
using SQL HEX function converts it but it is slow.

Here is a HEX value of Packed String

x'00000000000123'

SQL HEX function gives a value 123

RPG Move gives 12

Any better soloution please?

Thanks.
Dave McKenzie
2006-09-23 16:29:14 UTC
Permalink
The problem is the packed string doesn't have a sign (assuming it really
is decimal packed, and not binary). Here's one way to convert it:

d ds
d packed 1 8p 0
d hex 1 7

d packsign s 15p 0

c eval packed = 0
c eval hex = x'00000000000123'
c eval packsign = packed / 10

now packsign has a value of 123.

--Dave
Post by Iknir
I have uploaded a flat file with Packed Decimal String with a length 7.
It does not unpack properly using RPG simple "MOVE" op code. However,
using SQL HEX function converts it but it is slow.
Here is a HEX value of Packed String
x'00000000000123'
SQL HEX function gives a value 123
RPG Move gives 12
Any better soloution please?
Thanks.
Iknir
2006-09-23 16:51:56 UTC
Permalink
That worked. You are genious. Thank you very much Dave.

How will I know if packed data has a sign or not? Should I check for
"F" or "D" on a last byte?

I do not want to slow down the process. I think there should be an API.
Dave McKenzie
2006-09-23 17:20:05 UTC
Permalink
Yes, 'F' (positive) or 'D' (negative) in the right nibble of the last
byte is a sign. 'C' could also be used as a positive sign.

--Dave
Post by Iknir
That worked. You are genious. Thank you very much Dave.
How will I know if packed data has a sign or not? Should I check for
"F" or "D" on a last byte?
I do not want to slow down the process. I think there should be an API.
Iknir
2006-09-23 19:23:29 UTC
Permalink
How to check the right nibble?
Dave McKenzie
2006-09-23 20:03:43 UTC
Permalink
Well, let's see:

d ds
d packed8 1 8p 0
d packed7 1 7p 0
d hex 1 7
d hexlast 7 7

d lastnibble s 1a
d packsign s 15p 0

c eval packed8 = 0
c eval hex = x'00000000000123'
c eval lastnibble = %bitand(hexlast: x'0F')
c if lastnibble = x'0C' or
c lastnibble = x'0D' or
c lastnibble = x'0F'
* here if there's a sign
c eval packsign = packed7
c else
* here if there's no sign
c eval packsign = packed8 / 10
c endif

c eval *inlr = *on

--Dave
Post by Iknir
How to check the right nibble?
Iknir
2006-09-23 20:37:29 UTC
Permalink
Dave, Thank you,

I ran new conversion program for processing 65,000 records.

Embedded SQL with HEX function took 5 minutes and bogged down the
system.

RPG with Move and Validation took 10 seconds.

Regards.
Tom Liotta
2006-09-24 05:58:55 UTC
Permalink
Post by Iknir
I have uploaded a flat file with Packed Decimal String with a length 7.
It does not unpack properly using RPG simple "MOVE" op code. However,
using SQL HEX function converts it but it is slow.
Here is a HEX value of Packed String
x'00000000000123'
SQL HEX function gives a value 123
RPG Move gives 12
Any better soloution please?
Iknir:

Dave gave a perfectly good solution. Overall, the value that you showed
is in a representation known as (I think) BCD or 'binary coded decimal'.
When the digits are stored with the 4-bit rightmost sign, it becomes
'packed BCD' or packed decimal. I'm pretty sure I've seen the term
'packed' used for the storage scheme of your value, but I don't know how
commonly it would be called 'packed' on IBM EBCDIC (Extended Binary
Coded Decimal Interchange Code) systems.

Anyway, you also asked if there was an API. There are APIs available, so
I'll show an example usage in ILE RPG. The sample program has three
parms -- an input and two outputs. The first output is the input broken
out to its hex characters and the second output shows those hex
characters returned to the original byte format. That demonstrates the
two complementary APIs -- cvthc and cvtch.

There is also a test CL program that calls the RPG and dumps the parm
values. You can change the input value to see results. Test various
lengths to see how results can change.

Tom Liotta

----- Begin RPG
* Receives a 16-byte character value as input.
* Converts that to hex digits for output (displayable hex-nibbles).
* Then converts that hex back to char for output.
* Therefore, CharOut should equal CharIn.

H debug
H*option( *NoSrcStmt )
H dftactgrp( *NO )
H actgrp( *CALLER )
H bnddir( 'QC2LE' )
H indent( ' ' )
/eject
*--------------------------------------------------
* Procedure definition
*--------------------------------------------------

D HexChar PR extpgm( 'HEXCHAR' )
D CharIn 16a
Char in
D HexOut 32a
Hex out
D CharOut 16a
Char out

*--------------------------------------------------
* Procedure Interface
*--------------------------------------------------

D HexChar PI
D CharIn 16a
Char in
D HexOut 32a
Hex out
D CharOut 16a
Char out
/eject
D XC_ds Ds align
D dsCharIn 16
D dsHexOut 32
D dsCharOut 16

D CharSize s 10i 0

*
* Convert Hex-to-Character prototype...
* (Convert Hex-nibbles-to-Character-bytes prototype...)
* Length of receiver is double the length of source...
*
D cvthc PR ExtProc( 'cvthc' )
D receiver * Value
D source * Value
D size 10i 0 Value

*
* Convert Character-to-Hex prototype...
* (Convert Character-bytes-to-Hex-nibbles prototype...)
* Length of receiver is half the length of source...
*
D cvtch PR ExtProc( 'cvtch' )
D receiver * Value
D source * Value
D size 10i 0 Value

*
* Convert incoming character to hex...
*

C eval dsCharIn = CharIn
C eval dsHexOut = *blanks

* The size we need is the number of hex-nibbles...
* To include trailing blanks, do not use %trim()...
C eval CharSize = %len( %trim( dsCharIn )) * 2

C Callp cvthc( %Addr( dsHexOut )
c : %Addr( dsCharIn )
c : CharSize
c )

C eval HexOut = dsHexOut

*
* Convert derived hex to outgoing character...
*

* The size we need is the number of bytes of dsHexOut value...
* Note that we simply re-use the previous CharSize...

C Callp cvtch( %Addr( dsCharOut )
c : %Addr( dsHexOut )
c : CharSize
c )

C eval CharOut = dsCharOut

C eval *inLR = *on

C Return
----- End

----- Begin CL
pgm

dcl &CharIn *char 16 value( 'Some string ' )
dcl &HexOut *char 32 value( '***' )
dcl &CharOut *char 16 value( 'zzzzzzzzzzzzzzzz' )


call hexchar ( +
&CharIn +
&HexOut +
&CharOut +
)

dmpclpgm

endpgm
----- End

Tom Liotta

http://zap.to/tl400
Iknir
2006-09-24 20:20:55 UTC
Permalink
Tom,

API command executes much slower than simple move. With API, entire
process took about 5 minutes. Dave's method worked better and took just
5 seconds. I would stick to Dave's method of translating data.

Thanks both of you.
Tom Liotta
2006-09-24 20:47:01 UTC
Permalink
Post by Iknir
API command executes much slower than simple move. With API, entire
process took about 5 minutes. Dave's method worked better and took just
5 seconds. I would stick to Dave's method of translating data.
Iknir:

The use of memory definitions can speed many processes (and Dave knows
as well as anyone). I sent the API example simply because you asked if
one existed. But note that the API advantage is when you have different
fields of different lengths, possibly unknown when you write the
program. Also, once the API is learned, it can be used in any ILE language.

It's always nice to have alternatives.

Tom Liotta

http://zap.to/tl400

Continue reading on narkive:
Search results for 'Converting Packed String to Zoned Decimal' (Questions and Answers)
19
replies
Athens - A place to sleep and fun things to do around the city for 4 days?
started 2006-11-11 08:30:37 UTC
greece
Loading...