15

std::cout出力がすべてのプラットフォームで同じになるように、double値を移植可能(GCC、clang、MSVC ++)に出力したいと思います。

指数のフォーマットに問題があります。次のプログラム

#include <iostream>
int main()
{
    std::cout << 0.1e-7 << std::endl;
    return 0;
}

GCCでこの出力があります:

1e-08

およびMSVCでの次の出力

1e-008

どうすれば両方の出力を同じにすることができますか?

これがばかげた質問であるならば申し訳ありませんが、私は今のところ答えを見つけていません。すべてのフォーマットは、仮数の前のすべてのフォーマットを中心に進化しているようです...

編集:GCCの出力は(最初に述べたように)そうで1e-08ないので、適合しています。混乱させて申し訳ありません。1e-8

EDIT2:ディートマーの発言に続いて、実際には「仮数」の名前を「指数」に変更しました。ウィキペディアには仮数と仮数に関するセクションもあります

4

3 に答える 3

11

指数のフォーマットを制御するマニピュレーターはありません(仮数ではなく指数を意味していると思います。また、仮数に使用される「正式な」名前は重要です)。さらに悪いことに、指数のフォーマットを制限するC標準のルールが表示されません。これはC++に関するものだと思いますが、フォーマットの詳細を説明するために、C++標準はC標準を参照しています。

私が知っている唯一のアプローチはstd::num_put<char>、必要に応じて値をフォーマットする独自のファセットを使用することです。次に、このファセットはに入れられ、次にに入れstd::localeられimbue()ますstd::cout。実装の可能性としては、デフォルトのstd::num_put<char>ファセット(またはsnprintf()、残念ながら、おそらくより単純なファセット)を使用して浮動小数点数をフォーマットし、指数から先行ゼロを取り除くことができます。

于 2012-02-10T10:51:05.090 に答える
3

Dietmarの答えはクリーンで、おそらく本当にポータブルな答えですが、私は偶然に迅速で汚い答えを見つけました。MSVCは、_set_output_format「指数を2桁で印刷する」に切り替えるために使用できる機能を提供します。

次のRAIIクラスをmain()関数でインスタンス化して、GCC、CLANG、およびMSVCと同じ動作を提供できます。

class ScientificNotationExponentOutputNormalizer
{
public:
    unsigned _oldExponentFormat;

    ScientificNotationExponentOutputNormalizer() : _oldExponentFormat(0)
    {
#ifdef _MSC_VER
        // Set scientific format to print two places.
        unsigned _oldExponentFormat = _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
    }

    ~ScientificNotationExponentOutputNormalizer()
    {
#ifdef _MSC_VER
        // Enable old exponent format.
        _set_output_format(_oldExponentFormat);
#endif
    }
};
于 2012-02-10T12:16:15.837 に答える
2

問題は、VisualC++がC99標準に準拠していなかったことです。Visual C ++ 2015では_set_output_format、コンパイラが標準に準拠しているため、削除されました。

%eおよび%Eformat指定子は、浮動小数点数を10進仮数および指数としてフォーマットします。%gおよびformat指定子は%G、場合によっては、この形式で数値をフォーマットします。以前のバージョンでは、CRTは常に3桁の指数を持つ文字列を生成していました。たとえば、printf("%e\n", 1.0) を出力します1.000000e+000これは正しくありませんでした。Cでは、指数が1桁または2桁のみで表現できる場合、2桁のみが出力される必要があります

Visual Studio 2005では、グローバル適合スイッチが追加されまし_set_output_formatた。プログラムは、引数を指定してこの関数を呼び出し、_TWO_DIGIT_EXPONENT適合指数の印刷を有効にすることができます。デフォルトの動作は、標準に準拠した指数印刷モードに変更されました

Visual C++2015の重大な変更を参照してください。古いバージョンについては、@Manuelの回答を参照してください。

参考までに、C99標準では、次のように読むことができます。

e、E

浮動小数点数を表すdouble引数は、スタイル[-] d.ddd e(+-)ddに変換されます。ここで、小数点文字の前に1桁(引数がゼロ以外の場合はゼロ以外)があり、精度に等しい後の桁数。精度が欠落している場合は、6と見なされます。精度がゼロで、#フラグが指定されていない場合、小数点文字は表示されません。値は適切な桁数に丸められます。E変換指定子は、指数を導入するeの代わりにEを使用して数値を生成します。指数には常に少なくとも2桁が含まれ、指数を表すために必要な数の桁のみが含まれます。値がゼロの場合、指数はゼロです。無限大またはNaNを表すdouble引数は、fまたはF変換指定子のスタイルで変換されます。

これは、必要な指数の長さに関して何も示さなかったC90との違いです。

最近のVisualC++の変更は、印刷方法などにも関係していることに注意してnanくださいinf

于 2016-03-02T04:19:52.420 に答える