Home > front end >  How to remove trailing zeros with scientific notation when convert double to string?
How to remove trailing zeros with scientific notation when convert double to string?

Time:04-15

Live On Coliru

FormatFloat

I try to implement one conversion of Golang strconv.FormatFloat() in C .

#include <sstream>
#include <iostream>
#include <string>
#include <iomanip>

using namespace std;

std::string convert_str(double d)
{
    std::stringstream ss;
    if (d >= 0.0001)
    {
        ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
        ss << d;
        return ss.str();
    }
    else
    {
        ss << std::scientific;
        ss << d;
        return ss.str();
    }
}

int main()
{
    std::cout << convert_str(0.002) << std::endl; // 0.0020
    std::cout << convert_str(0.00001234560000) << std::endl; // 1.234560e-05
    std::cout << convert_str(0.000012) << std::endl; // 1.200000e-05

    return 0;
}

Output:

0.0020
1.234560e-05 // should be 1.23456e-05
1.200000e-05 // should be 1.2e-05

Question> How can I setup the output modifier so that the trailing zero doesn't show up?

strconv.FormatFloat(num, 'e', -1, 64)

The special precision value (-1) is used for the smallest number of digits necessary such that ParseFloat() will return f exactly.

CodePudding user response:

At the risk of being heavily downvoted criticised for posting a C answer to a C question ... you can use the %lg format specifier in a call to sprintf.

From cpprefernce:

Unless alternative representation is requested the trailing zeros are removed, also the decimal point character is removed if no fractional part is left.

So, if you only want to remove the trailing zeros when using scientific notation, you can change your convert_str function to something like the following:

std::string convert_str(double d)
{
    if (d >= 0.0001) {
        std::stringstream ss;
        ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
        ss << d;
        return ss.str();
    }
    else {
        char cb[64];
        sprintf(cb, "%lg", d);
        return cb;
    }
}

For the three test cases in your code, this will give:

0.0020
1.23456e-05
1.2e-05

From C 20 and later, the std::format class may offer a more modern alternative; however, I'm not (yet) fully "up to speed" with that, so I cannot present a solution using it. Others may want to do so.

CodePudding user response:

Yes, std::scientific don't remove trailing zeros from scientific notation. The good news, for your specific case, is that cout already format values below 0.0001 using scientific notation, and removing trailing zeros. So you can let your code like this:

#include <sstream>
#include <iostream>
#include <string>
#include <iomanip>

using namespace std;

std::string convert_str(double d)
{
    std::stringstream ss;
    if (d >= 0.0001)
    {
        ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
        ss << d;
        return ss.str();
    }
    else
    {
        ss << d;
        return ss.str();
    }
}

int main()
{
    std::cout << convert_str(0.002) << std::endl; // 0.0020
    std::cout << convert_str(0.00001234560000) << std::endl; // 1.23456e-05
    std::cout << convert_str(0.000012) << std::endl; // 1.2e-05
 
    return 0;
}
  •  Tags:  
  • c
  • Related