|
I looked at both cvtefni and cvtefnd before sending my note. I didn't like the looks of either version so I didn't talk about them. The CVTEFN MI instruction has all the goodness of being implemented below the MI. Can we write a routine in MI and make it bindable? Do you suppose that we could convince someone to create a MI function call that returns packed instead of int or double? The MI code to perform Ms. Morris' routine will look something like this: DCL DD SOURCE CHAR(32) BAS(P02); DCL DD RECEIVER PKD(30,9) BAS(P01); DCL DD MASK CHAR(3) BAS(P03); CVTEFN RECEIVER, SOURCE, MASK ; Obviously we need some message monitors and the entry plist but this is the functional code equivalent to the GETNUM routine. I think that it should be fast and it is nearly guaranteed to behave like reading numbers from a green screen. How did you produce your timing? The tried and true 10,000 iterations technique? Richard Jackson mailto:richardjackson@richardjackson.net www.richardjacksonltd.com Voice: 1 (303) 808-8058 Fax: 1 (303) 663-4325 -----Original Message----- From: owner-rpg400-l@midrange.com [mailto:owner-rpg400-l@midrange.com]On Behalf Of Mel Rothman Sent: Thursday, August 17, 2000 3:31 PM To: RPG400-L@midrange.com Subject: Re: Character to Decimal According to the MI Library reference, "The cvtefni and cvtefnd functions scans a character string for a valid decimal number in display format, removes the display character, and converts the result to integer (in the case of cvtefni) or double (in the case of cvtefnd)." Cvtefni handles only whole numbers. Cvtefnd's double lacks the required precision. Barbara Morris's solution overcomes both and it is much faster than cvtefnd. Using two versions of c2n subprocedures (not available for posting because of they are part of a copyrighted package), one using cvtefnd, the other a simplified version of Barbara's code, Barbara's code is 4.7 to 4.9 times faster. In both cases the input string is 30.9, '123456789012345678901.123456789'. More important, the cvtefnd version returns the wrong answer, 123456789012345683968.000000000 and Barbara's returns the right answer, 123456789012345678901.123456789. Mel Rothman Richard Jackson wrote: > > Can someone with access to an MI compiler post a program that contains > CVTEFN? It has got to be faster than this. > > Richard Jackson > mailto:richardjackson@richardjackson.net > www.richardjacksonltd.com > Voice: 1 (303) 808-8058 > Fax: 1 (303) 663-4325 > > -----Original Message----- > From: owner-rpg400-l@midrange.com [mailto:owner-rpg400-l@midrange.com]On > Behalf Of Mel Rothman > Sent: Thursday, August 17, 2000 1:45 PM > To: RPG400-L@midrange.com > Subject: Re: Character to Decimal > > Colin Thorpe wrote: > > > > Hi all, > > > > I am trying to take a character field (10A) containing something like > > 123.45bbbbb, > > And move it into a numeric field (12,2) 0000000123.45. > > > > The character field may or may not contain a decimal point. > > Therefore its value could be from .01 ==> 9999999999 > > > > Some time ago the C function ATOL was mentioned by Hans. > > > > I'm using V3R7 and managed to get his example working fine. > > > > Unfortunately this only returns the integer part of the value. > > > > I also tried ATOF but I'm not sure what the resulting value means. > 2235.14 > > = 1079246848 ? > > > > I can solve this problem using data structures and selects but I'm looking > > for an elegant ILE solution. > > > > Any help will be greatly appreciated. > > > > Thanks in advance > > > > Colin > > Colin, Barbara Morris from IBM's Toronto, Canada has posted the > following in several places. I think it is just what you are asking > for. > > Mel Rothman > > <-----* prototype for /COPY file start here -----> > > *--------------------------------------------------------- > * getNum - procedure to read a number from a string > * and return a 30p 9 value > * Parameters: > * I: string - character value of number > * I:(opt) decComma - decimal point and digit separator > * I:(opt) currency - currency symbol for monetary amounts > * Returns: packed(30,9) > * > * Parameter details: > * string: the string may have > * - blanks anywhere > * - sign anywhere > * accepted signs are: + - cr CR () > * (see examples below) > * - digit separators anywhere > * - currency symbol anywhere > * decComma: if not passed, this defaults to > * decimal point = '.' > * digit separator = ',' > * currency: if not passed, defaults to ' ' > * > * Examples of input and output (x means parm not passed): > * > * string | dec | sep | cursym | result > * ---------------+-----+-----+--------+------------ > * 123 | x | x | x | 123 > * +123 | x | x | x | 123 > * 123+ | x | x | x | 123 > * -123 | x | x | x | -123 > * 123- | x | x | x | -123 > * (123) | x | x | x | -123 > * 12,3 | , | . | x | 12.3 > * 12.3 | x | x | x | 12.3 > * 1,234,567.3 | x | x | x | 1234567.3 > * $1,234,567.3 | . | , | $ | 1234567.3 > * $1.234.567,3 | , | . | $ | 1234567.3 > * 123.45CR | x | x | x | -123.45 > * > * Author: Barbara Morris, IBM Toronto Lab > * Date: March, 2000 > *--------------------------------------------------------- > D getNum pr 30p 9 > D string 100a const varying > D decComma 2a const options(*nopass) > D currency 1a const options(*nopass) > > <-----* prototype for /COPY file end here -----> > > <-----* test program start here-----> > > * Copy prototype for procedure getNum > D/COPY GETNUM_P > > D res s like(getNum) > D msg s 52a > > C *entry plist > C parm p 32 > C parm dc 2 > C parm c 1 > > C select > C when %parms = 1 > C eval res = getNum(p) > C when %parms = 2 > C eval res = getNum(p : dc) > C when %parms = 3 > C eval res = getNum(p : dc : c) > C endsl > C eval msg = '<' + %char(res) + '>' > C msg dsply > > C return > > <-----* test program end here-----> > > <-----* module GETNUM start here -----> > > H NOMAIN > > * Copy prototype for procedure getNum > D/COPY GETNUM_P > > p getNum b > D getNum pi 30p 9 > D string 100a const varying > D decComma 2a const options(*nopass) > D currency 1a const options(*nopass) > > * defaults for optional parameters > D decPoint s 1a inz('.') > D comma s 1a inz(',') > D cursym s 1a inz(' ') > * structure for building result > D ds > D result 30s 9 inz(0) > D resChars 30a overlay(result) > * variables for gathering digit information > * pNumPart points to the area currently being gathered > * (the integer part or the decimal part) > D pNumPart s * > D numPart s 30a varying based(pNumPart) > D intPart s 30a varying inz('') > D decPart s 30a varying inz('') > * other variables > D intStart s 10i 0 > D decStart s 10i 0 > D sign s 1a inz('+') > D i s 10i 0 > D len s 10i 0 > D c s 1a > > * override defaults if optional parameters were passed > C if %parms > 1 > C eval decPoint = %subst(decComma : 1 : 1) > C eval comma = %subst(decComma : 2 :1) > C endif > > C if %parms > 2 > C eval cursym = currency > C endif > > * initialization > C eval len = %len(string) > * begin reading the integer part > C eval pNumPart = %addr(intPart) > > * loop through characters > C do len i > C eval c = %subst(string : i : 1) > > C select > * ignore blanks, digit separator, currency symbol > C when c = comma or c = *blank or c = cursym > C iter > * decimal point: switch to reading the decimal part > C when c = decPoint > C eval pNumPart = %addr(decPart) > C iter > * sign: remember the most recent sign > C when c = '+' or c = '-' > C eval sign = c > C iter > * more signs: cr, CR, () are all negative signs > C when c = 'C' or c = 'R' or > C c = 'c' or c = 'r' or > C c = '(' or c = ')' > C eval sign = '-' > C iter > * a digit: add it to the current build area > C other > C eval numPart = numPart + c > > C endsl > C enddo > > * copy the digit strings into the correct positions in the > * zoned variable, using the character overlay > C eval decStart = %len(result) - > %decPos(result) > C + 1 > C eval intStart = decStart - %len(intPart) > C eval %subst(resChars > C : intStart > C : %len(intPart)) > C = intPart > C eval %subst(resChars > C : decStart > C : %len(decPart)) > C = decPart > * if the sign is negative, return a negative value > C if sign = '-' > C return - result > * otherwise, return the positive value > C else > C return result > C endif > p e > > <-----* module GETNUM end here -----> +--- | This is the RPG/400 Mailing List! | To submit a new message, send your mail to RPG400-L@midrange.com. | To subscribe to this list send email to RPG400-L-SUB@midrange.com. | To unsubscribe from this list send email to RPG400-L-UNSUB@midrange.com. | Questions should be directed to the list owner/operator: david@midrange.com +--- +--- | This is the RPG/400 Mailing List! | To submit a new message, send your mail to RPG400-L@midrange.com. | To subscribe to this list send email to RPG400-L-SUB@midrange.com. | To unsubscribe from this list send email to RPG400-L-UNSUB@midrange.com. | Questions should be directed to the list owner/operator: david@midrange.com +---
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.