Как напечатать двойное значение с полной точностью с помощью cout?
Итак, я получил ответ на мой последний вопрос (не знаю, почему я об этом не подумал). Я печатал double
используя cout
это округлилось, когда я этого не ожидал. Как я могу сделать cout
печати double
используя полную точность?
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::исправлено.
На фиксированном обозначение, 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;
cout-это объект, который имеет кучу методов, которые вы можете вызвать для изменения точности и форматирования печатного материала.
существует setprecision(...) деятельность, но вы можете также установить другие вещи как ширина печати, etc.
посмотрите 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) точности. Слишком много ответов с точность не предоставляйте необходимое значение. Отсюда и ответ на старый вопрос.
- что база?
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
- иначе:
fixed
илиscientific
?
A double
это с плавающей точкой тип, а не фиксированная точка.
Do не использовать std::fixed
как это не удается напечатать small 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
- сколько точности (сколько всего цифры)?
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
). Тем не менее, поскольку это "работа" и вряд ли цель OP, она будет отложена.
обычно это 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