4

非科学的な(つまり、仮数/指数/ Eのない)文字列を使用して10進数を変換する必要があります。私のコードは次のようになります:

/*!
\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;
}

問題は、入力valがその場合1、関数が戻る1.000000が、の出力を期待していたことです1。また、コードをに変更するsprintf(doubleStr, "%1.0f", val);と正しく出力されますが1、入力valをに変更する0.000005と出力は0になり、出力が。になることを期待していました0.000005。したがって、基本的には、すべての出力をできるだけ短くし、不要なものをすべて削除する必要があり0ます。これはで可能sprintfですか?この機能で3.4E+/-38の範囲をサポートしたいと思います。

4

2 に答える 2

1

これはC++とタグ付けされているので、Cでは利用できないC ++機能を使用できると思います(そうでない場合は、教えてください。この回答を削除します)。

まず、std::string代わりに使用することをお勧めしchar*ます(これにより、バッファを管理するメモリから解放されます)?ostringstream次に、変換にaを使用することをお勧めします。

#include <sstream>

std::string ToDecimal(double val) {
    std::ostringstream oss;
    oss << val;
    return oss.str();
}
于 2013-03-24T19:48:59.857 に答える
1

c ++ iostream(具体的にはostringstream)は、よりもタスクに適していることがわかりますsprintf

std::fixedマニピュレータを使用して、科学的記数法を無効にします。std::setprecision精度(小数点以下の文字数)を指定するために使用します。あなたの場合、45の場所の精度は、すべてのfloat数値を表すのに十分なようです。

#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ます。(数値の大きさに応じて)一定でない精度を使用することもできますが、これを正しく行うには非常に注意が必要です。

代わりに、次の醜い(そして遅い)ハックを使用することができます:文字列の先頭をに変換してみて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;
}
于 2013-03-24T21:07:46.303 に答える