[Solved] convert int (which actually decimal) to string (1234 to “123.4”)


I was curious about the relative performance of these conversions so I did a few tests with the naive versions of a few methods. A few notes and caveats:

  • The below conversion codes have no error checking and haven’t been tested (i.e., don’t copy/paste the code).
  • Some methods only work for positive integers.
  • The methods do not have equivalent output. For example numbers 0-9 (‘0.0’, ‘.0’, ‘.’) and factors of 10 (’10’, ’10.’, ‘10.0’). You should decide exactly what output you want for these cases.
  • I would start by choosing the simplest algorithm and only optimize once it is found I need to. Do you really need performance of ~100 million integers/second?
  • Unfortunately, I don’t have a C++11 compiler to test the std::to_string() versions.

Algorithms tested are:

string toString1 (const int a)
{
    char buffer[32];
    string result = itoa(a, buffer, 10);
    char lastDigit = result[result.length() - 1];
    result[result.length() - 1] = '.';
    result += lastDigit;

    return result;
}

void toString1a (string& Output, const int a)
{
    char buffer[32];
    Output = itoa(a, buffer, 10);
    char lastDigit = Output[Output.length() - 1];
    Output[Output.length() - 1] = '.';
    Output += lastDigit;
}

string toString2 (const int a) {
    float f = a * 0.1f;
    ostringstream ss;
    ss << f;

    return ss.str();
}    

const char* toString3 (const int a)
{
    static char s_buffer[32]; //Careful!

    itoa(a, s_buffer, 10);
    size_t len = strlen(s_buffer);
    char lastDigit = s_buffer[len-1];
    s_buffer[len-1] = '.';
    s_buffer[len] = lastDigit;
    s_buffer[len+1] = '\0';

    return s_buffer;
}    

const char* toString4 (char* pBuffer, const int a)
{
    itoa(a, pBuffer, 10);
    size_t len = strlen(pBuffer);
    char lastDigit = pBuffer[len-1];
    pBuffer[len-1] = '.';
    pBuffer[len] = lastDigit;
    pBuffer[len+1] = '\0';

    return pBuffer;
}

void toString4a (char* pBuffer, const int a)
{
    itoa(a, pBuffer, 10);
    size_t len = strlen(pBuffer);
    char lastDigit = pBuffer[len-1];
    pBuffer[len-1] = '.';
    pBuffer[len] = lastDigit;
    pBuffer[len+1] = '\0';
}

const char* toString5 (char* pBuffer, const int a)
{
    snprintf(pBuffer, 16, "%.1f", a/10.0);
    return pBuffer;
}

const char* toString6 (char* pBuffer, const int a)
{
    snprintf(pBuffer, 16, "%d.%01d", a / 10, a % 10);
    return pBuffer;
}

string toString7 (const int a)
{
    ostringstream stream;
    stream << (a / 10) << '.' << (a % 10);
    return stream.str();
}

string toString8 (const int a)
{
    char buffer[16];
    string result = _itoa(a, buffer, 10);
    result.insert(result.length()-1, 1, '.'); 
    return result;
}

Basic benchmarks were run on the above methods for 100 million integers (starting from 0). If performance really matters for your case please profile/benchmark for yourself for your exact use-case.

  • toString1 = 0.64 sec (itoa to string)
  • toString1a = 0.61 sec (inplace, no return)
  • toString2 = 33.4 sec (stringstream, ouch!)
  • toString3 = 0.52 sec (itoa, static buffer)
  • toString4 = 0.52 sec (itoa)
  • toString4a = 0.52 sec (itoa, inplace)
  • toString5 = 6.35 sec (snprintf, float)
  • toString6 = 2.29 sec (snprintf, two ints)
  • toString7 = 33.3 sec (stringstream, two ints)
  • toString8 = 0.70 sec (itoa and string::insert)

Which one is “better” really depends on what you need. Personally I would use the simplest stream case (toString7) unless I was absolutely sure I needed the performance of the other methods.

3

solved convert int (which actually decimal) to string (1234 to “123.4”)