× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.


  • Subject: RE: Character to Numeric
  • From: boldt@xxxxxxxxxx
  • Date: Mon, 4 Dec 2000 10:14:48 -0500
  • Importance: Normal


At the risk of inflicting more physical abuse on a deceased
equine, I'd like to offer one more consideration on choosing
a method for converting character to numeric - performance.

Out of curiosity, I did a comparison between a number of
different methods for character to numeric conversion:

1) C run-time function "atof".  We know this suffers from
   accuracy problems with numbers bigger than about 15 digits,
   but I included it anyways as a benchmark.

2) The "#CtoN" function posted on the web page
   <http://www.bvstools.com/download.html>, but with the
   correction posted here by Barbara.

3) Barbara's "GetNum" procedure.

4) A simplified version of Barbara's GetNum procedure.
   (called "CharToNum")

Here are the results averaged from 5 runs on a lightly
loaded system.  Each procedure is called 100000 times in a
loop to convert the string '123456789.12345'.  Here are the
results:

CharToNum: 3983 ms   (fastest)
atof:      5568 ms
GetNum:    5968 ms
#CtoN:     9580 ms   (slowest)

Here are the results from converting the string '1234':

CharToNum: 1710 ms   (fastest)
atof:      2419 ms
#CtoN:     3329 ms
GetNum:    4943 ms   (slowest)

Here are the results from converting the string '1':

CharToNum: 1068 ms   (fastest)
#CtoN:     1974 ms
atof:      2683 ms   (slower than for '1234'!)
GetNum:    4485 ms   (slowest)

For smaller numbers (which arguably could be more common
in practice than big numbers), the standings change
considerably, and #CtoN moves up two places for the one
digit number.

Although "GetNum" and "CharToNum" use basically the same
method, "GetNum" is much more robust and can handle a wide
variety of different formats and sign characters.  These
two procedures are interesting in that basically no
arithmetic is involved in the conversion.  These procedures
consider character to numeric conversion as a string
manipulation problem.

For completeness, here's the source to the "CharToNum"
procedure.  I must warn that the procedure hasn't been
tested fully, but does work with a random selection of
values in the range 0.000000001 to
999999999999999999999.999999999.  (Program is in V5R1
syntax, but should be easy to rewrite into V4R4 RPG.)

-------------------------------------------------------------------------------

//----------------------------------------------------------------------//
     // Module: CHARTONUM
//
     //
//
     // Entries:
//
     //
//
     //   CharToNum  -- convert character string to packed numeric
//
     //
//

//----------------------------------------------------------------------//
     H nomain

     D CharToNum       PR            30P 9
     D    Str                        50A   VARYING CONST


//----------------------------------------------------------------------//
     // Exported procedure: CharToNum
//
     // Purpose: Convert a character string to decimal numeric
//

//----------------------------------------------------------------------//
     P CharToNum       B                   export
     D CharToNum       PI            30P 9
     D    Str                        50A   varying const

     D negative        S               N   inz(*OFF)

     D string          DS            30
     D    decnum                     30S 9 inz(0)

     D i               S             10I 0 inz(1)
     D digits          S             10I 0 inz(0)
     D decpos          S             10I 0 inz(0)
     D dec             S             10I 0 inz(0)
     D ch              S              1a
     D chtemp          S             30a   varying

      /free

       // Skip leading blanks (if any)
       dow i <= %len(Str) and %subst(Str:i:1) = ' ';
          i = i + 1;
       enddo;

       // Is string all blanks?
       if i > %len(Str);
          return 0;
       endif;

       // Is first non-blank char a minus sign?
       if %subst(Str:i:1) = '-';
          negative = *ON;
          i = i + 1;
       endif;

       // Skip leading zeros (if any)
       dow i <= %len(Str) and %subst(Str:i:1) = '0';
          i = i + 1;
       enddo;

       // Is string all zeros and blanks?
       if i > %len(Str);
          return 0;
       endif;

       // Loop through digits of string to be converted
       dow i <= %len(Str);
          ch = %subst(Str:i:1);
          if ch = '.';
             // We've reached the decimal point - only
             // one allowed
             if decpos <> 0;
                // We've already read a decimal point
                leave;
             endif;
             // Indicate decimal position just after last
             // digit read.
             decpos = digits + 1;

          elseif ch >= '0' and ch <= '9';
             // We've read a digit - save it
             digits = digits + 1;
             chtemp = chtemp + ch;

             // Have we read enough digits?
             if digits = 30;
                leave;
             endif;

          else;
             // Anything other than a digit or decimal point
             // ends the number
             leave;
          endif;

          // Advance to the next character
          i = i + 1;
       enddo;

       // Adjust decimal positions
       if decpos = 0;
          // If no decimal point coded, assume one after all digits
          decpos = %len(chtemp) + 1;
       else;
          // drop excess decimal digits
          dec = %len(chtemp) - decpos + 1;
          if dec > 9;
             %len(chtemp) = %len(chtemp) - (dec - 9);
          endif;
       endif;

       // Scale number appropriately
       %subst(string: 23-decpos: %len(chtemp)) = chtemp;

       // Set sign of result
       if negative;
          decnum = - decnum;
       endif;

       // Return answer
       return decnum;

      /end-free
     P CharToNum       E
-------------------------------------------------------------------------

Cheers!  Hans


Hans Boldt, ILE RPG Development, IBM Toronto Lab, boldt@ca.ibm.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 thread ...

Follow-Ups:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

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.