11

通貨の金額と価格を目的として、コード内のdoubleをg++のstd::decimal ::decimal32 / 64/128タイプに置き換えることを調査していますが、最適な入出力方法の点で立ち往生しています。データ。具体的には、文字列との間で変換するためのルーチンはないようであり、文字列ストリームメカニズムはこれらのタイプ用にコンパイルされません。これを行う唯一の方法は、中間型としてdoubleを使用することですが、常にdoubleを介して入力および出力する場合、これは10進数型を使用する目的を少なくとも部分的に無効にしますか?

私はここで何かを理解していないと確信しているので、これらのタイプの最適な使用方法に関するフィードバックを歓迎します。

編集:

私はいくつかの入出力ルーチンを一緒にハックしましたが、どちらにも本当に満足していません。入力はほとんど堅牢ではなく(科学的記数法のサポートなし)、出力ルーチンは単純化されており、二重変換のために非効率的であることは言うまでもありません。

#define MAX_DEC_LEN 17

std::decimal::decimal64 FromString(const char* str)
{
    if (strlen(str) > MAX_DEC_LEN)
        throw std::runtime_error("bad input");
    char buf[MAX_DEC_LEN+1];
    strncpy(buf, str, MAX_DEC_LEN+1);
    char* point(NULL); 
    if ((point = strchr(buf, '.')) != NULL)
        *(point++) = '\0';
    std::decimal::decimal64 ret(atoi(buf));
    if (point != NULL && *point != '\0')
    {
        int exponent(strlen(point));
        long long unsigned coeff(atoi(point));
        std::decimal::decimal64 d2(std::decimal::make_decimal64(coeff, -exponent));
        if (*buf == '-')
            ret -= d2;
        else
            ret += d2;
    }
    return ret;    
}

std::string ToString(std::decimal::decimal64 dec)
{
    double d(std::decimal::decimal_to_double(dec));
    std::ostringstream oss;
    oss << std::fixed << std::setprecision(6) << d;
    return oss.str();
}

私は本当にこれらの両方のために何かより良いものを求めています、そして物事を丸めるための(特定の精度への)ラウンド(しゃれを許してください)

4

1 に答える 1

6

Decimal TRは、それぞれセクション 3.2.10 と 3.2.11 で入力と出力のオーバーロードを定義します。見た目から、それらは gcc によって実装されていません。gcc での 10 進サポートは、文字列との間の変換ルーチンを提供する libdecnum の観点から実装されています。これらを使用して、I/O 演算子の簡単な実装を作成して開始します。

2012年 10 月 17 日の編集: gcc のライブラリ (およびファミリ) の 10 進数値のフォーマットをstd::decimal::decimal64調べると、残念ながら gcc は decNumber ライブラリ ヘッダーまたはライブラリをインストールしないことがわかりました。さらに、decNumberの他のソースは、gcc に同梱されているバージョンと完全に一致していません。その結果、10 進数をフォーマットするためにこれまでに見つけた唯一の方法は、gcc のコンパイル中に明示的な宣言を使用し、ライブラリ ビルドを使用することです。

かなり単純な実装ですが、単純な部分はソースです。まず、適切なヘッダーに入る宣言、たとえば<decimal/decimal>:

std::ostream& operator<< (std::ostream&, std::decimal::decimal32 const&);
std::ostream& operator<< (std::ostream&, std::decimal::decimal64 const&);
std::ostream& operator<< (std::ostream&, std::decimal::decimal128 const&);

オプションがない場合でも、何らかのフォーマットを行うかなり単純な実装は次のようになります。

extern "C" char* decimal32ToString(std::decimal::decimal32 const*, char*);
extern "C" char* decimal64ToString(std::decimal::decimal64 const*, char*);
extern "C" char* decimal128ToString(std::decimal::decimal128 const*, char*);

std::ostream& operator<< (std::ostream& out,
                          std::decimal::decimal32 const& value)
{
    char buffer[128];
    decimal32ToString(&value, buffer);
    return out << buffer;
}

std::ostream& operator<< (std::ostream& out,
                          std::decimal::decimal64 const& value)
{
    char buffer[128];
    decimal64ToString(&value, buffer);
    return out << buffer;
}

std::ostream& operator<< (std::ostream& out,
                          std::decimal::decimal128 const& value)
{
    char buffer[128];
    decimal128ToString(&value, buffer);
    return out << buffer;
}

-O1これを行っても、何らかのレベルの最適化(またはそれ以上)を使用しない限り、10 進数を使用して何かを構築できなかったという問題がまだ残っています。最適化が使用されない限り参照されないシンボルがありますが、これは値の出力とはまったく関係ありません。実装で使用される関数の定義を取得するには、libdecnumber.agcc のビルド中に作成されるライブラリにリンクする必要がありました。

g++ -o prog decimal-io.cpp main.cpp <gcc-build-root>/libdecnumber/libdecnumber.a

これとは別に、いくつかの拡張機能を備えたDecimal TRの独自の実装があり、decnumber ライブラリに基づいており、I/O を適切に実装しています。私の実装は、ある時点で公開されることを願っていますが、すぐには公開されません。

于 2012-10-12T19:22:41.307 に答える