IC SunsetThe developerWorks Connections platform will be sunset on December 31, 2019. On January 1, 2020, this forum will no longer be available. More details available on our FAQ.
Topic
  • 13 replies
  • Latest Post - ‏2019-07-20T21:35:31Z by MarinaSchwenk
MarinaSchwenk
MarinaSchwenk
6 Posts

Pinned topic Worth an RFE?

‏2019-07-03T21:23:39Z | bifs rpgle

Hello,

I have a question whether an idea would be worth entering a RFE. 

I would like to enter a RFE  to not require literal values in the %DEC BIF. 

What I attempted( and failed ) was trying to create a generic parse numeric procedure that would take a the string, length, precision, error and default that you could convert any text to a packed decimal and varying different lengths and precision. for example. I could call the procedure like this

MyCustomer = parsedNumeric( '123456', 0, -1, 8 : 0  ) and it would return a packed decimal allocated only at a 8:0

or I could call it passing

MyCompany = parsedNumeric( '12', 0, -1, 2: 0  ) and it would return a packed decimal allocated only at a 2:0

 

I have attached what I originally coded the procedure as.

I appreciate any response.

Thank you!

 

Marina Schwenk

 

 

 

  • barbara_morris
    barbara_morris
    605 Posts
    ACCEPTED ANSWER

    Re: Worth an RFE?

    ‏2019-07-03T21:51:02Z  

    Hi Marina, I'm sorry to say that the RFE would be rejected. It's not possible for RPG to have a built-in function that returns a value where the type of the returned value is not known until runtime.

    Would it work to define your procedure to return a value with 63 digits and say 15 decimal positions? You would code %dec(string:63:15) within the procedure. That wouldn't work if you wanted to get values with more than 48 integer places or 15 decimal positions, but otherwise, I think that would behave the same as returning a value with a specific length and decimal positions.

  • barbara_morris
    barbara_morris
    605 Posts

    Re: Worth an RFE?

    ‏2019-07-03T21:51:02Z  

    Hi Marina, I'm sorry to say that the RFE would be rejected. It's not possible for RPG to have a built-in function that returns a value where the type of the returned value is not known until runtime.

    Would it work to define your procedure to return a value with 63 digits and say 15 decimal positions? You would code %dec(string:63:15) within the procedure. That wouldn't work if you wanted to get values with more than 48 integer places or 15 decimal positions, but otherwise, I think that would behave the same as returning a value with a specific length and decimal positions.

  • MarinaSchwenk
    MarinaSchwenk
    6 Posts

    Re: Worth an RFE?

    ‏2019-07-04T19:02:57Z  

    Hi Marina, I'm sorry to say that the RFE would be rejected. It's not possible for RPG to have a built-in function that returns a value where the type of the returned value is not known until runtime.

    Would it work to define your procedure to return a value with 63 digits and say 15 decimal positions? You would code %dec(string:63:15) within the procedure. That wouldn't work if you wanted to get values with more than 48 integer places or 15 decimal positions, but otherwise, I think that would behave the same as returning a value with a specific length and decimal positions.

    Hi Barbara,

    Thank you for the response! I appreciate it.

    Its possible that would work. most of the time I would say that would be big enough to cover most cases. It Just also would mean all of our packed decimals are really big. I'll discuss it with the guys and see if we want to run that way.

    Thank you!

    Marina

  • barbara_morris
    barbara_morris
    605 Posts

    Re: Worth an RFE?

    ‏2019-07-04T19:28:15Z  

    Marina, you don't have to define your actual variables that big. Even if your procedure returns a packed(63:15) value, you can assign it to a value of any size.

    dcl-s myCustomer packed(8);

    dcl-pr parseNumeric packed(63:15);

    ...

    myCustomer = parseNumeric(...

  • TomLiotta
    TomLiotta
    29 Posts

    Re: Worth an RFE?

    ‏2019-07-13T09:35:57Z  

    It's not clear how this would materially differ from the existing Edit (QECEDT) API (possibly along with the Convert Edit Code (QECCVTEC) API or Convert Edit Word (QECCVTEW) API). Or perhaps the LBCPYNV MI builtin. That's what I've used in the past for similar problems.

    To clarify, QECEDT (et al.) allows you to pass in a value along with a description (e.g., data type, length) and return a fixed value. That fixed value can then be processed by RPG. A fairly straightforward service program proc can wrap various APIs to give your apparent result.

    Updated on 2019-07-13T09:56:54Z at 2019-07-13T09:56:54Z by TomLiotta
  • barbara_morris
    barbara_morris
    605 Posts

    Re: Worth an RFE?

    ‏2019-07-13T12:05:38Z  
    • TomLiotta
    • ‏2019-07-13T09:35:57Z

    It's not clear how this would materially differ from the existing Edit (QECEDT) API (possibly along with the Convert Edit Code (QECCVTEC) API or Convert Edit Word (QECCVTEW) API). Or perhaps the LBCPYNV MI builtin. That's what I've used in the past for similar problems.

    To clarify, QECEDT (et al.) allows you to pass in a value along with a description (e.g., data type, length) and return a fixed value. That fixed value can then be processed by RPG. A fairly straightforward service program proc can wrap various APIs to give your apparent result.

    Tom, the Edit and Convert Edit Code APIs are for converting numeric to character, but Marina wants to convert character to numeric, where the exact type of the numeric result isn't known until runtime. LBCPYNV can convert one numeric type to a different numeric type, but RPG can't use the result unless the result is a variable known to RPG.

  • scott_klement
    scott_klement
    304 Posts

    Re: Worth an RFE?

    ‏2019-07-14T14:09:49Z  

    The problem, as i see it, is that in every other language on earth this is easy:

     

    myNumVar = Number(myCharVar);

     

    But in RPG, you have to hard code a length/decpos.  sure, you can make your own solution, but it's expected that this is included in any language, and it makes RPG feel cumbersome.

  • MarinaSchwenk
    MarinaSchwenk
    6 Posts

    Re: Worth an RFE?

    ‏2019-07-15T15:37:15Z  

    Marina, you don't have to define your actual variables that big. Even if your procedure returns a packed(63:15) value, you can assign it to a value of any size.

    dcl-s myCustomer packed(8);

    dcl-pr parseNumeric packed(63:15);

    ...

    myCustomer = parseNumeric(...

    Hi Barbara,

    That is true. ( Sorry for the late response. I did not see the notification email held up on our email server ). You would just have to make sure the returning value is not larger than the decimal you are putting the numeric information in. Its something to consider.

    Thanks for the response :)

    Marina

  • MarinaSchwenk
    MarinaSchwenk
    6 Posts

    Re: Worth an RFE?

    ‏2019-07-15T15:42:29Z  

    The problem, as i see it, is that in every other language on earth this is easy:

     

    myNumVar = Number(myCharVar);

     

    But in RPG, you have to hard code a length/decpos.  sure, you can make your own solution, but it's expected that this is included in any language, and it makes RPG feel cumbersome.

    Hi Scott,

    You are correct. It is one of the things that causes the guys here who write in multiple languages grumble about RPG. I too wish it was that easy to convert character to numeric but, its just something that I accepted that RPG cannot do.

    Thanks for the response.

    Marina

  • TomLiotta
    TomLiotta
    29 Posts

    Re: Worth an RFE?

    ‏2019-07-16T12:05:57Z  

    Tom, the Edit and Convert Edit Code APIs are for converting numeric to character, but Marina wants to convert character to numeric, where the exact type of the numeric result isn't known until runtime. LBCPYNV can convert one numeric type to a different numeric type, but RPG can't use the result unless the result is a variable known to RPG.

    Barbara, true enough. But QECEDT (et al.) distinctions between 'character' and "*ZONED" and between "*ZONED" and 'numeric' are often chosen by the developer. QECEDT can take "*ZONED" input and return 'character' output that can be treated in RPG as zoned-decimal, with the right variable declarations. And since the input length is a parm, it may accept '12' one time and '123456' the next time, when stored in a generic character variable space.  The output can be placed into a declared space that RPG can handle.

    Regardless, I was looking more for a clearer description of the problem. A couple of use cases might help. Perhaps the  atoi() C library function would be what's actually needed, particularly if all values can be interpreted as integers. My only point is that various existing APIs might be appropriate if fuller specs are available.

  • barbara_morris
    barbara_morris
    605 Posts

    Re: Worth an RFE?

    ‏2019-07-16T16:50:43Z  

    My guess is that the main reason Marina wants to write an API to get the value from a string is that she wants to pass in a default value to use if there is an error. Using %DEC directly would require coding it in a MONITOR.

    By using %DEC with say length 63 and decimals 15, if the string was say "12345.67", and the target variable was packed(3:2), RPG wouldn't give an error for the %DEC, but it would give an error on the assignment from the procedure, so a MONITOR would still be needed unless the procedure did some extra checking.

    The procedure could use the required length and decimals to determine whether the result is too big.

    Something like this (tested a bit):

       dcl-s result packed(63:15);
       dcl-ds checkResultDs;
          checkResult zoned(63:15) inz(0);
          checkResultChar char(63) overlay(checkResult);
       end-ds;
       dcl-s start int(10);
       dcl-s integers int(10);

       // Get hival for the required length and decimals
       // If len = 4 and decimals = 1, we want checkResult
       // to have the value 999.9
       integers = len - decimals;
       start = 63 - 15 + 1; // start of decimal places
       %subst(checkResultChar : start : 1) = '9';
       start -= integers; // start of first integer place for all 9's
       %subst(checkResultChar : start : len) = *all'9';

       // Get the value from the string and make sure it's
       // not too big
       result = %dech(string : 63 : 15);

       if %abs(result) > checkResult);
          error = *on;
          result = default;
       endif;
       return result;

  • HowardChen
    HowardChen
    7 Posts

    Re: Worth an RFE?

    ‏2019-07-16T18:53:32Z  

    My guess is that the main reason Marina wants to write an API to get the value from a string is that she wants to pass in a default value to use if there is an error. Using %DEC directly would require coding it in a MONITOR.

    By using %DEC with say length 63 and decimals 15, if the string was say "12345.67", and the target variable was packed(3:2), RPG wouldn't give an error for the %DEC, but it would give an error on the assignment from the procedure, so a MONITOR would still be needed unless the procedure did some extra checking.

    The procedure could use the required length and decimals to determine whether the result is too big.

    Something like this (tested a bit):

       dcl-s result packed(63:15);
       dcl-ds checkResultDs;
          checkResult zoned(63:15) inz(0);
          checkResultChar char(63) overlay(checkResult);
       end-ds;
       dcl-s start int(10);
       dcl-s integers int(10);

       // Get hival for the required length and decimals
       // If len = 4 and decimals = 1, we want checkResult
       // to have the value 999.9
       integers = len - decimals;
       start = 63 - 15 + 1; // start of decimal places
       %subst(checkResultChar : start : 1) = '9';
       start -= integers; // start of first integer place for all 9's
       %subst(checkResultChar : start : len) = *all'9';

       // Get the value from the string and make sure it's
       // not too big
       result = %dech(string : 63 : 15);

       if %abs(result) > checkResult);
          error = *on;
          result = default;
       endif;
       return result;

    Agreed with Scott.

    And in RPG we can do:

    myNumVar = %float(myCharVar);

    It will work just like any other languages.

    or:

    exec sql set :myNumVar = float(myCharVar); 

    and round it to your decimal places:

    exec sql set :myNumVar = round(float(myCharVar),3); 

    Also agreed with Barbara, that a MONITOR (or TRY) group or some error checking code should be coded to test for data conversion errors.

     

  • MarinaSchwenk
    MarinaSchwenk
    6 Posts

    Re: Worth an RFE?

    ‏2019-07-20T21:34:49Z  
    • TomLiotta
    • ‏2019-07-16T12:05:57Z

    Barbara, true enough. But QECEDT (et al.) distinctions between 'character' and "*ZONED" and between "*ZONED" and 'numeric' are often chosen by the developer. QECEDT can take "*ZONED" input and return 'character' output that can be treated in RPG as zoned-decimal, with the right variable declarations. And since the input length is a parm, it may accept '12' one time and '123456' the next time, when stored in a generic character variable space.  The output can be placed into a declared space that RPG can handle.

    Regardless, I was looking more for a clearer description of the problem. A couple of use cases might help. Perhaps the  atoi() C library function would be what's actually needed, particularly if all values can be interpreted as integers. My only point is that various existing APIs might be appropriate if fuller specs are available.

    Hi Tom,

    The business cases I was trying to solve was, we have a lot of applications that are written to use CGIDEV2. Everything comes in as a string from the sencha UI and we have to convert the numeric  inputs into packed decimals. I was trying to create a universal procedure that will take all lengths and precisions that you could give it a default if the input is incorrect or a default error code if its fails due to some unexpected error.

    for example.

    housei      = %trim(zhbgetVarUpper( 'housei') );

    monitor;

    house = %dec( housei : 2 :0 )

    on-error;

    house = 0;

    endmon;

    would become

    house = parseDecimal( housei : 0 : -1 );

    = 0 default

    -1 = errorcode ;

    if ( house = -1 ) ;

    log it

    endif;

     

    Marina

     

     

  • MarinaSchwenk
    MarinaSchwenk
    6 Posts

    Re: Worth an RFE?

    ‏2019-07-20T21:35:31Z  

    My guess is that the main reason Marina wants to write an API to get the value from a string is that she wants to pass in a default value to use if there is an error. Using %DEC directly would require coding it in a MONITOR.

    By using %DEC with say length 63 and decimals 15, if the string was say "12345.67", and the target variable was packed(3:2), RPG wouldn't give an error for the %DEC, but it would give an error on the assignment from the procedure, so a MONITOR would still be needed unless the procedure did some extra checking.

    The procedure could use the required length and decimals to determine whether the result is too big.

    Something like this (tested a bit):

       dcl-s result packed(63:15);
       dcl-ds checkResultDs;
          checkResult zoned(63:15) inz(0);
          checkResultChar char(63) overlay(checkResult);
       end-ds;
       dcl-s start int(10);
       dcl-s integers int(10);

       // Get hival for the required length and decimals
       // If len = 4 and decimals = 1, we want checkResult
       // to have the value 999.9
       integers = len - decimals;
       start = 63 - 15 + 1; // start of decimal places
       %subst(checkResultChar : start : 1) = '9';
       start -= integers; // start of first integer place for all 9's
       %subst(checkResultChar : start : len) = *all'9';

       // Get the value from the string and make sure it's
       // not too big
       result = %dech(string : 63 : 15);

       if %abs(result) > checkResult);
          error = *on;
          result = default;
       endif;
       return result;

    Thanks Barbara!

    Yes this would work. I will implement it and see how it goes.

     

    Marina