Как напечатать двойное значение с полной точностью с помощью cout?


Итак, я получил ответ на мой последний вопрос (Я не знаю, почему я не подумал об этом). Я печатал double используя cout Это было округлено, когда я этого не ожидал. Как я могу сделать cout print a double используя полную точность?

11 277

11 ответов:

вы можете установить точность непосредственно на 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;

использовать std::setprecision:

std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;

вот что я бы использовал:

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

в основном пакет limits имеет черты для всех типов сборки.
Одним из признаков для чисел с плавающей запятой (float/double/long double) является атрибут digits10. Это определяет точность (я забыл точную терминологию) числа с плавающей запятой в базе 10.

см.:http://www.cplusplus.com/reference/std/limits/numeric_limits.html
Для получения подробной информации о других атрибутах.

путь 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;

выход:

Pi: 3.14159265358979

вот как отобразить двойник с полной точностью:

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

отображает:

100.0000000000005


max_digits10-это количество цифр, необходимых для однозначного представления всех различных двойных значений. max_digits10 представляет количество цифр до и после десятичной точки.


не используйте set_precision (max_digits10) с std::fixed.
На фиксированный нотация, 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

по полной точности я предполагаю, что достаточно точности, чтобы показать лучшее приближение к предполагаемому значению, но следует отметить, что double хранится с использованием представления базы 2 и база 2 не может представлять что-то столь же тривиальное, как 1.1 точно. Единственный способ получить полное полное точность фактического двойного (без ошибки округления) заключается в том, чтобы распечатать двоичные биты (или шестнадцатеричные nybbles). Один из способов сделать это-написать double до union и затем распечатка целочисленного значения битов.

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

это даст вам 100% точную точность двойника... и быть совершенно нечитаемым, потому что люди не могут читать двойной формат IEEE ! Википедия имеет хорошую запись о том, как интерпретировать двоичные биты.

в новом C++, вы можете сделать

std::cout << std::hexfloat << 1.1;
printf("%.12f", M_PI);

%.12f означает плавающую точку, с точностью до 12 цифр.

cout-это объект, который имеет кучу методов, которые вы можете вызвать, чтобы изменить точность и форматирование печатных материалов.

есть setprecision(...) деятельность, но вы можете также установить другие вещи как ширина печати, ЕТК.

посмотрите cout в ссылке вашей IDE.

наиболее переносимым...

#include <limits>

using std::numeric_limits;

    ...
    cout.precision(numeric_limits<double>::digits10 + 1);
    cout << d;

С ostream:: precision (int)

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

даст

3.141592653589793, 2.718281828459045

почему вы должны сказать "+1 " я понятия не имею, но дополнительная цифра, которую вы получаете из него, правильна.

как мне напечатать double значение с полной точностью с помощью cout?

использовать hexfloat или
используйте scientific и установите точность

std::cout.precision(std::numeric_limits<double>::max_digits10 - 1);
std::cout << std::scientific <<  1.0/7.0 << '\n';

// C++11 Typical output
1.4285714285714285e-01

слишком много ответов касаются только одного из 1) базы 2) фиксированной/научной компоновки или 3) точности. Слишком много ответов с точность не предоставляйте необходимое значение. Отсюда и этот ответ на старый вопрос.

  1. что база?

A double, безусловно, кодируется с помощью базы 2. Прямой подход с C++11 заключается в печати с использованием std::hexfloat.
Если не десятичный вывод является приемлемым, мы закончили.

std::cout << "hexfloat: " << std::hexfloat << exp (-100) << '\n';
std::cout << "hexfloat: " << std::hexfloat << exp (+100) << '\n';
// output
hexfloat: 0x1.a8c1f14e2af5dp-145
hexfloat: 0x1.3494a9b171bf5p+144

  1. в противном случае:fixed или scientific?

A double это с плавающей точкой тип, а не фиксированная точка.

Do не использовать std::fixed как это не удается напечатать маленький double как угодно, но 0.000...000. Для больших double, он печатает много цифр, возможно сотни сомнительной информативности.

std::cout << "std::fixed: " << std::fixed << exp (-100) << '\n';
std::cout << "std::fixed: " << std::fixed << exp (+100) << '\n';
// output
std::fixed: 0.000000
std::fixed: 26881171418161356094253400435962903554686976.000000 

для печати с полной точностью, сначала используйте std::scientific, который будет "писать значения с плавающей точкой в научной нотации". Обратите внимание, что по умолчанию 6 цифр после десятичной запятой, недостаточное количество, обрабатывается в следующей точке.

std::cout << "std::scientific: " << std::scientific << exp (-100) << '\n';  
std::cout << "std::scientific: " << std::scientific << exp (+100) << '\n';
// output
std::scientific: 3.720076e-44
std::scientific: 2.688117e+43

  1. сколько точности (сколько всего цифры)?

A double кодируется с помощью двоичной базы 2 кодирует ту же точность между различными степенями 2. Это часто 53 бит.

[1.0...2.0) есть 253 разные double,
[2.0...4.0) есть 253 разные double,
[4.0...8.0) есть 253 разные double,
[8.0...10.0) есть 2/8 * 253 другой double.

но если код печатается в десятичном виде с N значащие цифры, количество комбинаций [1.0...10.0) - это 9/10 * 10N.

все N (точность) выбирается, не будет взаимно однозначного отображения между double и десятичных текст. если фиксированный N выбирается, иногда это будет немного больше или меньше, чем действительно необходимо для некоторых double значения. Мы могли бы ошибиться на слишком мало (a) ниже) или слишком многие (b) ниже).

кандидат 3 N:

a) используйтеN поэтому при преобразовании из текстаdouble-текст мы приходим к одному и тому же тексту для всех double.

std::cout << dbl::digits10 << '\n';
// Typical output
15

b) используйтеN так что при конвертации из doubleтекстdouble мы приходим к тому же double для всех double.

// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17

, когда max_digits10 недоступно, обратите внимание, что из-за атрибутов base 2 и base 10, digits10 + 2 <= max_digits10 <= digits10 + 3, мы можем использовать digits10 + 3 для обеспечения достаточно печатаются десятичные цифры.

c) используйтеN это зависит от значения.

это может быть полезно, когда код хочет отображать минимальный текст (N == 1) или точно стоимостью double (N == 1000-ish в случае denorm_min). Но поскольку это "работа" и вряд ли цель ОП, она будет отложена.


обычно это b), который используется для "печати a double значение с полной точностью". Некоторые приложения могут предпочесть а) ошибка при предоставлении слишком большого количества информации.

с .scientific,.precision() задает количество цифр после десятичной точки, так 1 + .precision() цифры печатаются. Код должен max_digits10 всего цифр так .precision() с max_digits10 - 1.

typedef std::numeric_limits< double > dbl;
std::cout.precision(dbl::max_digits10 - 1);
std::cout << std::scientific <<  exp (-100) << '\n';
std::cout << std::scientific <<  exp (+100) << '\n';
// Typical output
3.7200759760208361e-44
2.6881171418161356e+43

аналогичный вопрос C