How to implement Std::to_string for floating point?

Asked

Viewed 273 times

4

This question may seem more like a request, but I’ve been researching it for 2 months and I don’t know how to solve it. I need to implement the std::to_string in C++ (headless) in a way that accepts decimal values (float, double). What is the most appropriate way? Note that i am implementing my own std::string.

3 answers

5

  • His recommendation as well as his practice shows that he has excellent performance, as can be seen here http://www.boost.org/doc/libs/1_55_0/doc/html/boost_lexical_cast/performance.html

3


Since you did not specify any constraints for the implementation, the simplest way to do that I would imagine would be:

std::string to_string(float f) {
    std::ostringstream buffer;
    buffer << f;
    return buffer.str();
}

And the same after double and long double.

It would also be valid to have an array of char large enough and use sprintf.

EDIT:

As stated in the comments, it is to be an implementation on the arm. An algorithm I implemented quickly to do this is as follows:

std::string to_string(double value, unsigned precision=2) {

    const bool negative = value < 0;
    if (negative) {
        value *= -1;
    }

    //Move a casa decimal para a esquerda o quanto for necessário
    for (unsigned i=0; i<precision; ++i) {
        value *= 10;
    }

    //Converte para inteiro e calcula quantos dígitos vai ter
    unsigned long long i_value = value;
    int digits_count = 0;
    for (unsigned long long v=i_value; v!=0; v /= 10) {
        ++digits_count;
    }

    std::string result;
    result.resize(digits_count+1); //+1 para o '.';

    //Converte para string e põe o '.' no lugar necessário
    int prec_counter = precision;
    for (int pos = result.size()-1; pos >= 0; --pos) {

        if (prec_counter == 0) {
            result[pos] = '.';
        }
        else {
            int digit = i_value % 10;
            i_value /= 10;
            result[pos] = '0' + digit;
        }
        --prec_counter;
    }

    //Remove zeros à direita depois do . decimal
    if (precision > 0) {
        while (result.back() == '0') {
            result.pop_back();
        }
        if (result.back() == '.') {
            result.pop_back();
        }
    }

    return (negative ? "-" : "") + result;
}

This is a simple and limited algorithm, but it can serve as a basis for something more elaborate. I haven’t tested much, and he doesn’t handle special cases, like NAN. I’m assuming that your std::string has the functions I used.

  • I can only use a "string", I need to use C++ without any header.

  • How to use string and at the same time use no header? What are your actual requirements?

  • @Guilhermebernal I implemented my own string.

  • 1

    In this case it is more complicated. If you want an exact representation you will have to study the IEEE specification. But for something quick and simple, I would start testing by special cases (NAN, +/- infinity, etc.). Then convert to integer (via cast) and generate that part. Finally I would take the fractional part (original number - truncated number), multiply by 100, 1000, 10000 (depends on the accuracy you want) and convert that part. Obviously check to not put unnecessary zeros on the left.

  • Thank you very, very much! I had this idea of the same sleeping algorithm, but forgot :P

2

The simplest way to implement the function is to rely on std::stringstream using the operators of std::ostream which will already be implemented for the standard types and several custom types. This would make your function work for most types. An example of implementation:

#include <string>
#include <sstream>

template <typename T>
std::string to_string(const T& value) {
    std::stringstream ss;
    ss << value;
    return ss.str();
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.