Natural Formating of Numeric Data

Help!

I have the following Problem given:
A Copycode which gets

&1& a numeric variable / value
&2& an alphanumeric variable

How could i transfer the numeric value to the alphanumeric variable with decimal point and thousands separators without defining any other help- or counter variable?

E.g.:

&1& = -123456.789
&2& should be -123.456,789

another example:

&1& = 1234567.12
&2& should be 1.234.567,12

and one more:

&1& = -0.213
&2& should be -0,213

And don’t forget i could not define a new variable at this context. I tried move edited with examine what would not solve the problem because the inputvariable could have dynamic lenghts. I also tried compress numeric but there i don’t know how i could get the thousands separators.

I use Natural 4.1.4 on BS2000

Greetings
Sascha

p.s. i know how to make it as an subprogram or with defining new variables.

Hi Sascha,
I know you may think this is cheating, but what about making an external subroutine with two parameters “by value” and “by value return”
and then put the call of this subroutine into a piece of copycode with placeholders ?

Finn

Sounds nice. Hmmm i think i would try that first. But if someone have an other better solution please post.

Greetings
Sascha

Hi Sascha,
I hope this fits to your requirement:

DEFINE DATA LOCAL
1 #N1 (N17.3) INIT <-123456.789>
1 #N2 (N8.2) INIT <1234567.12>
1 #N3 (N1.3) INIT <0.213>
1 #N4 (N22.7)
INIT <-1234567890123456789012.1234567>
1 #A (A40)
END-DEFINE
INCLUDE T-COMMC ‘#N1’ ‘#A
WRITE #A
INCLUDE T-COMMC ‘#N2’ ‘#A
WRITE #A
INCLUDE T-COMMC ‘#N3’ ‘#A
WRITE #A
INCLUDE T-COMMC ‘#N4’ ‘#A
WRITE #A
*
END

The Copycode T-COMMC:

MOVE EDITED &1&
(EM=-Z’$‘ZZZ’$‘ZZZ’$‘ZZZ’$‘ZZZ’$‘ZZZ’$‘ZZZ’$'ZZ9.9999999)
TO &2&
EXAMINE FULL &2& FOR ‘.’ REPLACE ‘,’
EXAMINE FULL &2& FOR ‘$’ REPLACE ‘.’
MOVE RIGHT JUSTIFIED &2& TO &2&

I am running Natural 4.1.3 on MVS, so I am not sure what the differences are, but what kind of problems does this code create for you:

The program looks like:

RESET #A (A9) #N(N5.2)
MOVE 2345.55 TO #N
INCLUDE SLBCOPY ‘#N’ ‘#A
END

The copy code looks like:

MOVE EDITED &1& (EM=ZZZ,ZZZ,ZZ9.99) TO &2&
WRITE ‘=’ &1& ‘=’ &2&

This works on the mainframe with different size variables being passed to it.

I hope, I understand your problem correctly. How about that copycode:

*
if frac(&1&) eq 0
  move edited &1& (EM=-Z,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZ9) to &2&
  move left &2& to &2&
else
  move edited &1& (EM=-Z,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZ9.99999999999999) to &2&
/* cut trailing zeros
  examine &2& for '0' replace ' '
  move left &2& to &2&
  examine &2& for ' ' replace '0'
end-if

Only disadvantage is, that the receiving alpha-field must be at least 15 byte long in case of frac(&1&) ne 0.

If the variable contains the value 0.123, the 0 gets lost because of the EXAMINE REPLACE

You’re right. The code for cutting trailing zeros should be:

/* cut trailing zeros 
move left &2& to &2& 
examine &2& from 2 for '0' replace ' ' 
examine &2& for ' ' replace '0' 

Hmmm i think this is an PEBKAC i tried this myself before i wrote the first posting and got an Compileerror for the Editmask. If i try it now i don’t get such an error :?

But thanks i will try it again. And write if i get the Error again :smiley:

Greetings
Sascha

I tried the whole Copycode:


*
0020 IF FRAC(&1&) EQ 0
0030   MOVE EDITED &1& (EM=-Z,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZ9) TO &2&
0040   MOVE LEFT &2& TO &2&
0050 ELSE
0060   MOVE EDITED &1& (EM=-Z,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZ9.99999999999999) TO &2&
0070 /* cut trailing zeros
0080   MOVE LEFT &2& TO &2&
0090   EXAMINE &2& FROM 2 FOR '0' REPLACE ' '
0100   EXAMINE &2& FOR ' ' REPLACE '0'
0110 END-IF

and if i use it i get an NAT0285 in Line 0090, FROM using

Greetings
Sascha

In the Cut Trailing Zeros, try this:

/* CUT TRAILING ZEROS
MOVE LEFT &2& TO &2&
EXAMINE &2& FOR ‘0’ REPLACE ’ ’
EXAMINE &2& FOR ’ ’ REPLACE ‘0’

I am not sure what the from parameter does, it’s not valid in MVS, but if its valid in BS2000, you may just need the & around the 2 after from. The original look like:
EXAMINE &2& FROM 2 FOR ‘0’ REPLACE ’ ’

Maybe it was suppose to be

EXAMINE &2& FROM &2& FOR ‘0’ REPLACE ’ ’

Natural 6 allows a position clause in the EXAMINE statement with which you can set the starting and ending bytes with FROM and THRU keywords. This is not available in Natural 4.

On the mainframe, use the SUBSTRing clause instead.

EXAMINE SUBSTR (&2&, 2) FOR '0' REPLACE ' '

Just wishful thinking… It would be nice if SAG can add a keyword (to include the thousands separator) to the COMPRESS NUMERIC statement to do what Sascha requires.

I think I know the answer to my own question, but will ask it anyway. Do you have existing code with INCLUDEs and two arguments?

If not, I would ask why you are going to do this with copycode. Can we not trust a Natural programmer to write a simple MOVE EDITED statement? That way we do not have to write code to deal with the possibility that we have N7.2 or N9.1 or N6.0 etc.

Except for the possibility that you might reverse your commas and periods , it does not seem to me there is a likelihood of changing everything that would use this copycode.

Okay, if a format changes from N7.2 to N9.3, I would have to SCAN a program for where the variable is used, and would have to alter an edit mask.

steve

ACK! Compress numeric would be a proper way to solve this. MOVE EDITED produces a runtime error if the target field is too small. COMPRESS doesn’t. And COMPRESS would even work with floats.

Hi Steve yes i have existing Code. This Copycode would be Part of a Framework to Convert Dates, Numerics and logical Variables to Alphanumeric and back. I wrote an Generator which writes Programms using this Copycodes. (The generated Code should also be Humanreadable ;-)) Thats why i could not invent an new Variable without changing existing Programms and/or changing the Generator

But the solutions here in this Thread would work for me. (I solved the “from”-Problem with an “if” where i every time when i have a positive Value between 0 and 1 compress the “0” to the first position so i could use the other code from Matthias.

Greetings
Sascha

If the copycode has to work for floats, we can use a compress numeric before doing an move edited…

compress numeric &1& to &2&
/* float or number less than thousand
if substr(&2&,3,1) = '.' or substr(&2&,2,1) = '.'
    or &1& < 1000 and &1& > -1000
  ignore /* use compress numeric as a result
else
  if frac(&1&) eq 0
    move edited &1& (EM=-Z,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZ9) to &2&
    move left &2& to &2&
  else
    move edited &1& (EM=-Z,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZZ,ZZ9.9(14)) to &2&
    /* cut trailing zeros
    move left &2& to &2&
    examine &2& from 2 for '0' replace ' '
    examine &2& for ' ' replace '0'
  end-if
*
end-if