Итак, я получил ответ на мой последний вопрос (я не знаю, почему я не подумал об этом). Я печатал double
использование, cout
которое округлилось, когда я не ожидал этого. Как я могу сделать cout
печать с double
использованием полной точности?
Итак, я получил ответ на мой последний вопрос (я не знаю, почему я не подумал об этом). Я печатал double
использование, cout
которое округлилось, когда я не ожидал этого. Как я могу сделать cout
печать с double
использованием полной точности?
Ответы:
Вы можете установить точность непосредственно std::cout
и использовать std::fixed
спецификатор формата.
double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;
Вы можете #include <limits>
получить максимальную точность поплавка или удвоения.
#include <limits>
typedef std::numeric_limits< double > dbl;
double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;
cout.precision(numeric_limits<double>::digits10 + 2);
получаю только 16 ....
max_digits10
чтобы обозначить то же самое. Исправлен ответ, чтобы отразить это.
Используйте std::setprecision
:
std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;
std::setprecision (17)
удвоен, см. Комментарии к ответу @Bill The Lizard.
Вот что я бы использовал:
std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
<< 3.14159265358979
<< std::endl;
По сути, пакет limit имеет черты для всех встроенных типов.
Одной из особенностей чисел с плавающей запятой (float / double / long double) является атрибут digits10. Это определяет точность (я забыл точную терминологию) числа с плавающей запятой в базе 10.
См. Http://www.cplusplus.com/reference/std/limits/numeric_limits.html
Подробнее о других атрибутах.
std::setprecision()
: #include <iomanip>
std::numeric_limits<double>
вместоnumberic_limits<double>
1
в std::numeric_limits<double>::digits10
?
max_digits10
, а не произвольно digits10+2
. В противном случае, в случае float
, long double
, boost::multiprecision::float128
это не получится , так как вы должны были бы +3
вместо +2
.
Путь 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
оно хранится с использованием представления базы 2, а база 2 не может представлять что-то столь же тривиальное, как 1.1
точное. Единственный способ получить полную-полную точность фактического двойного значения (без NO ROUND OFF ERROR) - это распечатать двоичные биты (или шестнадцатеричные биты). Один из способов сделать это - записать в double
a, 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;
Вот как отобразить двойной с полной точностью:
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
Примечание. Требуются заголовочные файлы.
#include <iomanip>
#include <limits>
100.0000000000005
не представляется точно как double
. (Может показаться, что так и должно быть, но это не так, потому что он нормализуется , т.е. его двоичное представление). Чтобы убедиться в этом, попробуйте: 100.0000000000005 - 100
. Мы получаем 4.973799150320701e-13
.
Как напечатать
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
- это тип с плавающей запятой , а не с фиксированной запятой .
Как не использовать , 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
double
Кодируется с использованием двоичного основанием 2 кодируют такую же точность между различными полномочиями 2. Это часто 53 бит.
[1.0 ... 2.0) есть 2 53 разных double
,
[2.0 ... 4.0) есть 2 53 разных double
,
[4.0 ... 8.0) есть 2 53 разных double
,
[8.0 ... 10.0) есть 2 / 8 * 2 53 разных double
.
Тем не менее , если код печатает в десятичном с N
значащими цифрами, число комбинаций [1,0 ... 10,0) составляет 9/10 * 10 N .
Независимо от того, какой N
(точность) выбран, не будет взаимно-однозначного сопоставления между double
десятичным текстом. Если N
выбрано фиксированное значение , иногда оно будет немного больше или меньше, чем необходимо для определенных double
значений. Мы могли бы ошибиться на слишком мало ( a)
ниже) или слишком много ( b)
ниже).
3 кандидата N
:
а) Используйте N
так при преобразовании из double
текстового текста мы получаем один и тот же текст для всех double
.
std::cout << dbl::digits10 << '\n';
// Typical output
15
б) Используйте N
так при преобразовании из double
-text-, 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
). Тем не менее, поскольку это «работа» и маловероятная цель ОП, она будет отложена.
Обычно б) используется для «печати 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
//1234567890123456 17 total digits
precision()
устанавливая количество знаков после запятой для научного режима. Без указания scientific
он устанавливает общее количество цифр, исключая показатель степени. Вы все равно можете получить научный вывод, в зависимости от вашего числового значения, но тогда вы также можете получить меньше цифр, чем вы указали. Пример: cout.precision(3); cout << 1.7976931348623158e+308; // "1.8e+308"
результаты printf
могут быть разными. Непонятные вещи, которые следует знать.
char buf[DBL_DECIMAL_DIG + 3 + 5]; sprintf(buf, "%.*g", DBL_DECIMAL_DIG, d);
дополнительные символы для: знак, десятичная точка, завершающий ноль, e [+ | -], 3 цифры для показателя степени ( DBL_MAX_10_EXP = 308). Следовательно, общее количество необходимых символов - 25.
printf("%.12f", M_PI);
% .12f означает с плавающей запятой с точностью до 12 цифр.
Наиболее переносимо ...
#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», я понятия не имею, но дополнительная цифра, которую вы получаете из этого, правильна.
Это покажет значение до двух десятичных знаков после точки.
#include <iostream>
#include <iomanip>
double d = 2.0;
int n = 2;
cout << fixed << setprecison(n) << d;
Смотрите здесь: Запись с фиксированной точкой
Использовать фиксированную запись с плавающей точкой Устанавливает фиксированный флаг формата float для потока str.
Если для поля с плавающей запятой задано фиксированное значение, значения с плавающей запятой записываются с использованием записи с фиксированной запятой: значение представляется с точно таким количеством цифр в десятичной части, которое указано в поле точности (точность), и без экспоненты.
Установить десятичную точность Устанавливает десятичную точность, которая будет использоваться для форматирования значений с плавающей запятой в выходных операциях.
Если вы знакомы со стандартом IEEE для представления чисел с плавающей запятой, вы должны знать, что невозможно вывести числа с плавающей запятой с полной точностью вне области действия стандарта , то есть это всегда приведет к округление реальной стоимости.
Вы должны сначала проверить, находится ли значение в области , если да, тогда используйте:
cout << defaultfloat << d ;
Использовать стандартную нотацию с плавающей точкой Устанавливает флаг формата float для потока str в defaultfloat.
Если для параметра float установлено значение defaultfloat, значения с плавающей точкой записываются с использованием нотации по умолчанию: представление использует столько значащих цифр, сколько необходимо, до десятичной точности (точности) потока, считая как цифры до, так и после десятичной точки (если есть) ).
Это также поведение по умолчанию cout
, что означает, что вы не используете его явно.
fixed
? Сdouble h = 6.62606957e-34;
,fixed
дает мне0.000000000000000
иscientific
выводы6.626069570000000e-34
.