简体   繁体   中英

What's the fastest or most efficient way to convert a double value to its most concise string representation?

I'm trying to write a C++ function that takes as input an arbitrary double value and converts it into a string that meets three requirements:

  • When the string is converted back into a double, it will be exactly the same value as the original double
  • The string is of the shortest length possible
  • The string does not use scientific notation, eg 0.00123 not 1.23e-3

I have an implementation of this function that works, but using the first naïve method that came to mind:

#include <string>
#include <sstream>

using namespace std;

string doubleToString(double d, int precision)
{
    ostringstream ss;
    ss.setf(ios_base::fixed);
    ss.precision(precision);
    ss << d;
    return ss.str();
}

string convertDoubleToStringConciselyAndAccurately(double d)
{
    // a precision of 325 seems to be accurate enough to represent any double,
    // as the minimum positive double value has an exponent of -324 (at least
    // on the platforms I care about)
    const int maxPrecision = 325;

    for(int precision = 1; precision < maxPrecision; ++precision) {
        string possibleResult = doubleToString(d, precision);
        double d2 = atof(possibleResult.c_str());

        if (d == d2) {
            cout << precision << "\n";
            return possibleResult;
        }
    }

    return doubleToString(d, maxPrecision);
}

When this function is called with a double that requires lots of precision, such as a representation of an irrational number, it will usually have to make 16 attempts at converting it. If the number has a very small exponent, such as 1e-300 , it can take hundreds of attempts. This isn't particularly fast or efficient!

So what would be a faster, more efficient, or perhaps more elegant way to implement this?

In fact, I'm wondering what's the fastest way of implementing this that we can figure out? Or the most efficient? Or both?

Note: I understand that for the vast majority of use cases the implementation I wrote is plenty fast and efficient enough — I'm not trying to micro-optimize. I'm asking this question purely for the intellectual curiosity of it, and so that I might learn something.

edit: My original implementation of the function had an error, where it assumed the maximum precision necessary for any double was 17. This is not true, as it doesn't cover doubles like 1e-100.

edit 2: I found an easy optimization, which is to figure out the exponent of the double value and use that as a starting point when searching for the right precision. Should mean that the function won't take more than 17 attempts to find the correct precision:

string convertDoubleToStringConciselyAndAccurately(double d)
{
    const int maxPrecision = 325;
    int minPrecision = 1;

    if (d < 0.1) {
        minPrecision = (int)floor(-log10(d));
    }

    for(int precision = minPrecision; precision < maxPrecision; ++precision) {
        string possibleResult = doubleToString(d, precision);
        double d2 = atof(possibleResult.c_str());

        if (d == d2) {
            return possibleResult;
        }
    }

    return doubleToString(d, maxPrecision);
}

在C ++ 17,我相信你可以只使用std::to_charsstd::chars_format::fixed规定。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM