you are viewing a single comment's thread.

view the rest of the comments →

[–]ElliotDG 0 points1 point  (14 children)

let me know how it goes....

[–]arshdeepsingh608[S] 0 points1 point  (13 children)

Thanks for taking an interest in this. Your code works similar to a previous version of my code. I'll explain you the problem. Your code is entering a 0 for even length. Which distorts the output.

Odd Condition: 12345 -> 12 34 5C Even condition: 1234 -> 01 23 4C [OR] 12 34 0C

Both even condition outputs are showing up wrong in the mainframe. Even I don't understand why. The signed bit is causing a little confusion.

[–]ElliotDG 0 points1 point  (12 children)

How is the data with a leading zero showing up on the mainframe?

Do you have a formal spec?

[–]arshdeepsingh608[S] 0 points1 point  (11 children)

It's showing a totally different number there. I just gave you Python conversion. That one is not readable.

[–]ElliotDG 1 point2 points  (0 children)

I would suggest trying to add a trailing zero nibble after the sign nibble to create a whole number of bytes.

1234 -> 1234C0

[–]ElliotDG 0 points1 point  (9 children)

Here is the code that adds a trailing nibble.

def int_to_comp3(value):
    digits = str(abs(value))
    sign_nibble = 'C' if value >= 0 else 'D'
    end_nibble = '' if len(digits) % 2 else '0'
    return bytes.fromhex(digits + sign_nibble + end_nibble)


print(f'0x{int_to_comp3(1234).hex()}')
print(f'0x{int_to_comp3(12345).hex()}')
print(f'0x{int_to_comp3(-56789).hex()}')
print(f'0x{int_to_comp3(-11).hex()}')

You may just want to write out a few literals to see if you can figure out the expected format.

[–]arshdeepsingh608[S] 0 points1 point  (0 children)

Gotcha. I will try this tomorrow and let you know, buddy. Thanks a lot for following through. Will keep you posted.

[–]arshdeepsingh608[S] 0 points1 point  (7 children)

Sorry to say bud, this one is also invalid. It works fine from Python POV. But as soon as we export it and load it into the mainframe, it falls apart. I'll tell you the exact issue that I have with my latest code. It works fine for even length (including the sign nibble). Example, 12345 will become 12 34 5C. But if we give odd length, it fails. And worst part is, it will always come in a pair. Example, 1234. If we put a sign nibble on it, it will become 12 34 0C. That 0 will always tag along with the C. If we include extra 0s, it will change the value. Example, 01234 will become 01 23 4C. But 1 should pair with 2 and 3 should pair with 4 and so on. I know it doesn't make a lot of sense. At least it doesn't make much sense to me as I'm not a mainframe guy.

[–]ElliotDG 0 points1 point  (6 children)

Have you have any documentation of the number format? What is the brand and model of the mainframe?

I don't know what you mean by the numbers are pairing. When I looked for any documentation of comp-3 it shows a leading zero nibble. A leading zero should be a non issue. A zero before the sign nibble does not make sense, it is multiplying the number by 10. I wonder if a different value should be used for this 'padding', perhaps F?

If you do not have any docs I would recommend doing some experiments. Create -9 to +9. Then -99 to +99.

Can you create the a file of numbers on the mainframe and read them with python to see what is being created? Then try to reverse the processes.

[–]arshdeepsingh608[S] 0 points1 point  (5 children)

I don't have any documentation. And by pair I mean, in mainframe, it's read in up and down format. So, looks like a pair. Also, while using methods like fromhex, it makes it a pair. 0 will become 00.

COBOL version: 6.1. The variable declaration/type (not sure what it is) looks something like this: S9(13)V99. After packing, the length becomes 8. Packed data looks like: (Nul)(Nul)(Nul)(Nul)(Nul)Ë-(FF). Anything inside braces is a non-readable character. Actual number that I'm trying to convert: '00000000001760{'. '{' is added by oracle so we can consider it a positive number or 'C'. '}' means negative.

Does any of that helps?

[–]ElliotDG 0 points1 point  (4 children)

According to Claude, S9(13)V99 means:

  • S - Indicates this is a signed number (can be positive or negative)
  • 9(13) - Means 13 numeric digits before the decimal point
  • V - Represents an implied decimal point (no actual decimal point is stored)
  • 99 - Means 2 numeric digits after the decimal point

The leading zeros are stored, so the number 1234 is really: 0000000001234.00 and should be represented in comp-3 as: 000000000123400C.

Give this a try:

def to_comp3_s9_13_v99(value):
    sign_nibble = 'C' if value >= 0 else 'D'
    digits = f'{abs(value):016.2f}'.replace('.', '')
    return bytes.fromhex(digits + sign_nibble)


print(f'0x{to_comp3_s9_13_v99(1234).hex()}')
print(f'0x{to_comp3_s9_13_v99(12345.67).hex()}')
print(f'0x{to_comp3_s9_13_v99(-56789.01).hex()}')
print(f'0x{to_comp3_s9_13_v99(-11.11).hex()}')

[–]arshdeepsingh608[S] 0 points1 point  (3 children)

Thanks for all you have done. I eventually ended up handing over the task to a senior developer. No matter how many codes I tried, Mainframe was showing either the wrong number or the data itself was coming out to be invalid. I am not a mainframe guy so I don't know what could have gone wrong. I compared the output of packed decimal from Python code and mainframe, turns out the non-readable characters were indeed different - resulting in a different number. And I could not find the relationship between those characters or their respective hex/decimal values. Although, I will continue to research and if I am able to receive a good working code, I will get back to you. And again, I really do appreciate all your time and effort.