Тож я отримав відповідь на своє останнє запитання (не знаю, чому я не думав про це). Я друкував 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.