It would be very nice for you to redo this investigation using more up to date compilers.

I am curious to see the conversion to float also.

Great job and very well presented. ]]>

If you factor out that pow() the naive function in the linked code runs about twice as fast.

change ‘n’ to a double starting at 1.0

then multiply by 10 each loop

and divide by n.

that changed my ~0.05 sec to ~0.025 for 1 million random text-doubles timed with chrono. ]]>

http://pastebin.com/dHP1pgQ4 ]]>

It is as fast as the fastest of your code! Testet with gcc 4.7 linux:

#define white_space(c) ((c) == ‘ ‘ || (c) == ‘\t’)

#define valid_digit(c) ((c) >= ‘0’ && (c) <= '9')

template

bool naive(T & r, const char *p) {

// Skip leading white space, if any.

while (white_space(*p) ) {

p += 1;

}

r = 0.0;

int c = 0; // counter to check how many numbers we got!

// Get the sign!

bool neg = false;

if (*p == ‘-‘) {

neg = true;

++p;

}else if(*p == ‘+’){

neg = false;

++p;

}

// Get the digits before decimal point

while (valid_digit(*p)) {

r = (r*10.0) + (*p – ‘0’);

++p; ++c;

}

// Get the digits after decimal point

if (*p == ‘.’) {

T f = 0.0;

T scale = 1.0;

++p;

while (*p >= ‘0’ && *p std::numeric_limits::max_exponent10 ){

e = std::numeric_limits::max_exponent10;

}else if(e < std::numeric_limits::min_exponent10 ){

e = std::numeric_limits::max_exponent10;

}

// SECOND CHECK:

if(c==0){return false;} // we got no exponent! this was not intended!!

T scaleE = 1.0;

// Calculate scaling factor.

while (e >= 50) { scaleE *= 1E50; e -= 50; }

//while (e >= 8) { scaleE *= 1E8; e -= 8; }

while (e > 0) { scaleE *= 10.0; e -= 1; }

if (negE){

r /= scaleE;

}else{

r *= scaleE;

}

}

// POST CHECK:

// skip post whitespaces

while( white_space(*p) ){

++p;

}

if(*p != ”){return false;} // if next character is not the terminating character

// Apply sign to number

if(neg){ r = -r;}

return true;

}

@stringstream: when you only measure the timings of serializing the values (and not the storing the values in the stringstream container) the timings are identical with atof and strtod.

e.g.

{

double tsum = 0.0;

std::vector timings;

timings.reserve(R);

std::stringstream* ss = new std::stringstream[N];

for (size_t r=0 ; r<R ; ++r) {

for (size_t i=0 ; i<nums.size() ; ++i) {ss[i].str(nums[i]); }

ticks start = getticks();

for (size_t i=0 ; i> x;

tsum += x;

}

ticks end = getticks();

double timed = elapsed(end, start);

timings.push_back(timed);

}

delete[] ss;

std::cout << "stringstream without init: ";

PrintStats(timings);

std::cout << std::endl;

std::cout << tsum << std::endl;

}

The tests used in that library for string to double/float conversion are a little more extensive.

At the end of the article a number of comparisons between, stdlib, Boost, Spirit and StrTk can be found using various hardware configurations/compilers etc.

]]>http://www.leapsecond.com/tools/fast_atof.c

It’s a replacement for atof() – much faster.

]]>