Тож я отримав відповідь на своє останнє запитання (не знаю, чому я не думав про це). Я друкував 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;
В основному пакет обмежень має риси для всіх типів збірки.
Однією з ознак чисел з плаваючою комою (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;
Вихід:
Пі: 3.14159265358979
З повною точністю я припускаю, що середня точність відображає найкраще наближення до передбачуваного значення, але слід зазначити, що double
зберігається за допомогою представлення бази 2, а база 2 не може представляти щось настільки тривіальне, як 1.1
саме. Єдиний спосіб отримати повну точність фактичного подвійного (без ПОМИЛКИ ВИМКУВАННЯ КРУГЛИ) - роздрукувати двійкові біти (або шістнадцяткові nybbles). Один із способів цього зробити - це 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 :: fix.
У фіксованій нотації 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
:
a) Використовуйте 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
недоступно, зауважте, що через атрибути бази 2 та бази 10 digits10 + 2 <= max_digits10 <= digits10 + 3
ми можемо використати digits10 + 3
для того, щоб надрукувати достатню кількість десяткових цифр.
в) Використовуйте значення, 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 :: точність (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;
Дивіться тут: Позначення з фіксованою точкою
Використовувати фіксовану нотацію з плаваючою комою Встановлює прапор формату floatfield для потоку str на фіксований.
Коли для плаваючого поля встановлено фіксований, значення з плаваючою комою записуються за допомогою позначення з фіксованою точкою: значення подається рівно стільки цифр у десятковій частині, скільки визначено полем точності (точності) і без частини експонента.
Встановити десяткову точність Встановлює десяткову точність, яка буде використовуватися для форматування значень з плаваючою комою у вихідних операціях.
Якщо ви знайомі зі стандартом IEEE для представлення плаваючих точок, ви знаєте, що неможливо показувати плаваючі точки з точністю поза рамками стандарту , тобто це завжди призведе до округлення реальної величини.
Спочатку потрібно перевірити, чи є значення в межах , якщо так, то використати:
cout << defaultfloat << d ;
Використовувати нотацію з плаваючою комою за замовчуванням Встановлює прапор формату floatfield для потоку str на defaultfloat.
Коли для floatfield встановлено значення defaultfloat, значення з плаваючою комою записуються за допомогою позначення за замовчуванням: представлення використовує стільки значущих цифр, скільки потрібно до десяткової точності (точності) потоку, підраховуючи обидві цифри до і після десяткової крапки (якщо такі є ).
Це також поведінка за замовчуванням cout
, що означає, що ви не використовуєте це явно.
fixed
? Зdouble h = 6.62606957e-34;
,fixed
дає мені0.000000000000000
іscientific
виводить6.626069570000000e-34
.