404

以前の質問では、予想外のときに丸くなったdouble使用を印刷していました。完全な精度を使用して印刷するcoutにはどうすればよいですか?coutdouble

4

16 に答える 16

469

精度を直接設定し、書式指定子std::coutを使用できます。std::fixed

double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;

#include <limits>float または double の最大精度を取得できます。

#include <limits>

typedef std::numeric_limits< double > dbl;

double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;
于 2009-02-16T18:38:50.290 に答える
83

使用std::setprecision:

#include <iomanip>
std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;
于 2009-02-16T18:18:08.513 に答える
27

これが私が使用するものです:

std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
          << 3.14159265358979
          << std::endl;

基本的に、limits パッケージにはすべての組み込みタイプの特性があります。
浮動小数点数 (float/double/long double) の特性の 1 つは digits10 属性です。これは、基数 10 の浮動小数点数の精度 (正確な用語は忘れました) を定義します。

参照: http://www.cplusplus.com/reference/std/limits/numeric_limits.html
他の属性の詳細について。

于 2009-02-16T22:10:04.150 に答える
15

std::formatC++20 では、これを行うために使用できます。

std::cout << std::format("{}", M_PI);

出力 (IEEE754 と仮定double):

3.141592653589793

デフォルトの浮動小数点形式は、ラウンドトリップが保証された最短の 10 進数表現です。I/O マニピュレータと比較したこの方法の利点は、setprecision不要な数字を出力しないことです。

それまでの間、ベースになっている {fmt} ライブラリを使用できます。std::format{fmt} は、printこれをさらに簡単かつ効率的にする機能も提供します ( godbolt )。

fmt::print("{}", M_PI);

免責事項: 私は {fmt} と C++20 の作成者std::formatです。

于 2020-12-16T19:19:17.153 に答える
14

iostreams の方法はちょっとぎこちないです。boost::lexical_cast適切な精度を計算するため、使用することを好みます。そして、それも速いです。

#include <string>
#include <boost/lexical_cast.hpp>

using boost::lexical_cast;
using std::string;

double d = 3.14159265358979;
cout << "Pi: " << lexical_cast<string>(d) << endl;

出力:

円周率: 3.14159265358979

于 2011-08-05T17:35:07.943 に答える
11

double を完全な精度で表示する方法は次のとおりです。

double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;

これは次のように表示されます。

100.0000000000005


max_digits10 は、すべての個別の double 値を一意に表すために必要な桁数です。max_digits10 は、小数点の前後の桁数を表します。


std::fixed で set_precision(max_digits10) を使用しないでください。
固定表記では、set_precision() は小数点以下の桁数のみを設定します。max_digits10は小数点の前後の桁数を表すため、これは正しくありません。

double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;

これは間違った結果を表示します:

100.00000000000049738

注: ヘッダー ファイルが必要です

#include <iomanip>
#include <limits>
于 2016-01-01T13:57:17.447 に答える
10

double完全な精度では、意図した値の最良の近似値を表示するのに十分な平均精度を想定していますが、基数 2 表現を使用して格納されていることを指摘する必要があります1.1実際の double の完全な精度 (ROUND OFF ERROR なし)を取得する唯一の方法は、バイナリ ビット (または 16 進数のニブル) を出力することです。

これを行う 1 つの方法は、 a を使用してを整数unionにタイプパンdoubleし、整数を出力することです。これは、整数は切り捨てや丸めの問題に悩まされないためです。(このような型パニングは C++ 標準ではサポートされていませんが、C ではサポートされています。ただし、ほとんどの C++ コンパイラはおそらく正しい値を出力します。g++ はこれをサポートしていると思います。)

union {
    double d;
    uint64_t u64;
} x;
x.d = 1.1;
std::cout << std::hex << x.u64;

これにより、double の 100% 正確な精度が得られます...人間は IEEE double 形式を読み取ることができないため、まったく読み取ることができません! ウィキペディアには、バイナリ ビットを解釈する方法に関する優れた記事があります。

新しいC++では、次のことができます

std::cout << std::hexfloat << 1.1;
于 2015-10-24T20:36:30.767 に答える
3
printf("%.12f", M_PI);

%.12f は、精度が 12 桁の浮動小数点を意味します。

于 2010-01-24T17:34:56.330 に答える
1

最も携帯性に...

#include <limits>

using std::numeric_limits;

    ...
    cout.precision(numeric_limits<double>::digits10 + 1);
    cout << d;
于 2009-02-16T18:39:43.830 に答える
1

この質問では、double を無損失で文字列に変換する方法についての説明があります (Octave では、C++ で簡単に再現できます)。人間が読める短い float の説明と、16 進形式のロスレスな説明を用意することをお勧めします。例: pi -> 3.14{54442d18400921fb}。

于 2021-04-26T12:01:09.890 に答える
0

これは、 だけでなく、任意の浮動小数点型で機能する関数であり、double後で見つかった方法でストリームを戻します。残念ながら、スレッドとはうまくやり取りできませんが、それが iostream の性質です。ファイルの先頭に次のインクルードが必要です。

#include <limits>
#include <iostream>

関数は次のとおりです。頻繁に使用する場合は、ヘッダー ファイルで使用できます。

template <class T>
void printVal(std::ostream& os, T val)
{
    auto oldFlags = os.flags();
    auto oldPrecision = os.precision();

    os.flags(oldFlags & ~std::ios_base::floatfield);
    os.precision(std::numeric_limits<T>::digits10);
    os << val;
    
    os.flags(oldFlags);
    os.precision(oldPrecision);
}

次のように使用します。

double d = foo();
float f = bar();
printVal(std::cout, d);
printVal(std::cout, f);

通常の挿入演算子を使用できるようにしたい場合は、次の<<追加のラッパー コードを使用できます。

template <class T>
struct PrintValWrapper { T val; };
template <class T>
std::ostream& operator<<(std::ostream& os, PrintValWrapper<T> pvw) {
    printVal(os, pvw.val);
    return os;
}
template <class T>
PrintValWrapper<T> printIt(T val) {
    return PrintValWrapper<T>{val};
}

これで、次のように使用できます。

double d = foo();
float f = bar();
std::cout << "The values are: " << printIt(d) << ", " << printIt(f) << '\n';
于 2020-06-23T16:11:07.970 に答える
-1

ostream::precision(int) を使用

cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;

譲ります

3.141592653589793, 2.718281828459045

「+1」と言わなければならない理由はわかりませんが、得られる余分な数字は正しいです。

于 2009-08-11T11:28:59.150 に答える