c – sprintf太多/几位小数

我必须使用非科学(即无尾数/指数/ E)字符串转换十进制数字.我的代码看起来像这样:

/*!
\brief Converts a <em>XML Schema Decimal</em>
*/
char *ToDecimal(double val) const
{
    const size_t nMax = 200;
    char *doubleStr = new char[nMax];

    sprintf(doubleStr, "%1.6f", val);

    return doubleStr;
}

问题是,当输入值为1时,函数返回1.000000,但我希望输出为1.另外,如果我将代码更改为sprintf(doubleStr,“%1.0f”,val);然后它正确输出1,但如果输入val变为0.000005,则输出为0,我希望输出为0.000005.所以基本上我希望所有输出都尽可能短,并删除所有不必要的0. sprintf可以实现吗?我想用这个功能支持3.4E / – 38范围.

最佳答案 事实证明,c iostreams(特别是ostringstream)比sprintf更适合你的任务.

使用std :: fixed操纵器禁用科学记数法.使用std :: setprecision指定精度(小数点后的字符数).在您的情况下,45个位置的精度似乎足以表示所有浮点数.

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

std::string convert(double x)
{
    std::ostringstream buffer;
    buffer << std::fixed << std::setprecision(45) << x;
    std::string result = buffer.str();

    return result;
}

此外,要清除结果,请删除任何尾随零.

    size_t i = result.find_last_not_of('0');
    if (result[i] != '.')
        ++i;
    result.erase(i);

注意:尾随零的清除仅适用于可精确表示的数字(如0.75或0.03125):例如,数字0.1将转换为0.10000000000000000555111512312578270211815834.可以使用非恒定精度(取决于数字的大小),但要做到这一点非常棘手.

相反,可以使用以下丑陋(和缓慢)的hack:尝试将字符串的开头转换回double,如果结果等于初始数字,则剪切字符串.

size_t i;
for (i = 1; i < result.size(); ++i)
{
    std::istringstream cut(result.substr(0, i));
    double temp;
    cut >> temp; // the verbose syntax could fit into one line 
    if (temp == x) // by using boost::lexical_cast
        break;
}
点赞