Performance - Floating point doubles to string conversion

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
cbruce
Posts: 163
Joined: Sep 12, 2007 19:13
Location: Dallas, Texas

Performance - Floating point doubles to string conversion

Post by cbruce »

/'
Ok, @dodicat got me started down the rabbit-hole of floating point double to string conversion performance in my original post @:
viewtopic.php?t=31450

Here's a slightly modified version of @dodicat's test code from:
viewtopic.php?p=289648#p289648

dodicat's C-lib snprintf(dbl)-to-zstring shows an average 28% better performance than native FB str(dbl)-to-string.

But dodicat was using 'dim as double d = 13.004' which hid a small detail related to snprintf()... snprintf(), (and all of the printf() family's variations when converting floating point values using the 'g' or 'G' specifier), has a default precision of only six (6) *significant* digits. Since dodicat's version used the default precision, snprintf() was not doing as much work as FB's str() and gave much better performance times.

After switching snprintf() to a floating point format string with 16 digits of precision, ("%.16g"), snprintf(dbl)-to-zstring only shows a 12% better performance than str(dbl)-to-string.

Also of note is that *all* of a double's characters impact the overall parsing performance of snprintf(). If the double is negative, the '-' character is additional overhead. The same thing if the double has an exponent; that 'E-004" adds a lot (relatively) of performance impact.

This shows that common use of str(dbl) is fine, but for critical performance, snprintf(dbl) is the one to choose - (just make sure to set the precision to meet your requirements).
'/

Code: Select all

#include "crt.bi"
const as integer ITERATIONS = 1000000
dim as zstring*24 sz
dim as string ss
dim as double d
dim as double t

RANDOMIZE , 3  ' Choose FreeBASIC Mersienne Twister RND() and seed it with a random seed value.

for j as integer = 1 to 2
  if j = 1 then d = 0.5429259254597127
  if j = 2 then d = -0.5429259254597127e-9

  print
  print str(d);" = Double to convert to String"
  print
  print "[Result]";tab(31);"[Time]";tab(60);"[Convert floating point Doubles to ZStrings / Strings]"
  print

  for k as integer = 1 to 2
          
    t=timer      
    for n as long=1 to ITERATIONS
      snprintf(@sz, 24, "%g", d)
    next
    print sz;tab(30);timer-t;tab(60);"Zstring = snprintf(DOUBLE) -- 6 digits"
          
    t=timer      
    for n as long=1 to ITERATIONS
      snprintf(@sz, 24, "%.16g", d)
    next
    print sz;tab(30);timer-t;tab(60);"Zstring = snprintf(DOUBLE) -- 16 digits"

    t=timer
    for n as long=1 to ITERATIONS
      sz=str(d)
    next
    print sz;tab(30);timer-t;tab(60);"Zstring = STR(DOUBLE)"

    t=timer
    for n as long=1 to ITERATIONS
      ss=str(d)
    next
    print ss;tab(30);timer-t;tab(60);"String  = STR(DOUBLE)"

    print

  next k
next j

end
Results:

Code: Select all

0.5429259254597127 = Double to convert to String

[Result]                      [Time]                       [Convert floating point Doubles to ZStrings / Strings]

0.542926                      0.347559200017713            Zstring = snprintf(DOUBLE) -- 6 digits
0.5429259254597127            0.4633024999639019           Zstring = snprintf(DOUBLE) -- 16 digits
0.5429259254597127            0.5621779999928549           Zstring = STR(DOUBLE)
0.5429259254597127            0.5508228000253439           String  = STR(DOUBLE)

0.542926                      0.3492437000386417           Zstring = snprintf(DOUBLE) -- 6 digits
0.5429259254597127            0.4629746000282466           Zstring = snprintf(DOUBLE) -- 16 digits
0.5429259254597127            0.5597476999973878           Zstring = STR(DOUBLE)
0.5429259254597127            0.5506630999734625           String  = STR(DOUBLE)


-5.429259254597127e-010 = Double to convert to String

[Result]                      [Time]                       [Convert floating point Doubles to ZStrings / Strings]

-5.42926e-010                 0.4747977999504656           Zstring = snprintf(DOUBLE) -- 6 digits
-5.429259254597127e-010       0.5822030999697745           Zstring = snprintf(DOUBLE) -- 16 digits
-5.429259254597127e-010       0.6784165999852121           Zstring = STR(DOUBLE)
-5.429259254597127e-010       0.6684604999609292           String  = STR(DOUBLE)

-5.42926e-010                 0.4798713000491262           Zstring = snprintf(DOUBLE) -- 6 digits
-5.429259254597127e-010       0.5838622000301257           Zstring = snprintf(DOUBLE) -- 16 digits
-5.429259254597127e-010       0.6792778999079019           Zstring = STR(DOUBLE)
-5.429259254597127e-010       0.6711904000258073           String  = STR(DOUBLE)
Thanks!
CBruce
Post Reply