كيف يمكنني طباعة قيمة مزدوجة بدقة كاملة باستخدام cout؟
-
23-08-2019 - |
سؤال
لذلك حصلت على الجواب على بلدي السؤال الأخير (لا أعرف لماذا لم أفكر في ذلك).كنت أطبع أ 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;
نصائح أخرى
يستخدم 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;
أساسا حزمة الحدود لديها سمات لجميع البناء في أنواع.
واحدة من سمات أرقام النقطة العائمة (تعويم / مزدوج / طويل مزدوج) هي سمة أرقام 10. هذا يحدد الدقة (نسيت المصطلحات الدقيقة) لرقم نقطة عائمة في قاعدة 10.
يرى: http://www.cplusplus.com/Reference/std/limits/numeric_limits.html.
للحصول على تفاصيل حول السمات الأخرى.
طريقة iOStreams هي نوع من clunky. انا افضل 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
ملاحظة: ملفات الرأس المطلوبة
#include <iomanip>
#include <limits>
بالدقة الكاملة، أفترض دقة متوسطة كافية لإظهار أفضل تقريب للقيمة المقصودة، ولكن تجدر الإشارة إلى ذلك double
يتم تخزينه باستخدام تمثيل الأساس 2 ولا يمكن أن يمثل الأساس 2 شيئًا تافهًا مثل 1.1
بالضبط.الطريقة الوحيدة للحصول على ممتلئ ممتلئ دقة المضاعفة الفعلية (مع عدم وجود خطأ في التقريب) هي طباعة البتات الثنائية (أو القضم السداسي).إحدى الطرق للقيام بذلك هي كتابة 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;
كيف يمكنني طباعة
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) الدقة. الكثير من الإجابات مع الاحكام لا تقدم القيمة المناسبة اللازمة. ومن هنا هذه الإجابة على سؤال قديم.
- ما قاعدة؟
أ 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
?
أ 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) هناك 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 * 10ن.
ما من أي وقت مضى N
(الدقة) يتم اختياره، لن يكون هناك رسم خرائط فردية بين double
والنص العشري. إذا تم إصلاحها N
يتم اختيارها، وأحيانا ستكون أكثر أو أقل قليلا من اللازمة حقا لبعض double
القيم. يمكن أن نخرأ على عدد قليل جدا (a)
أدناه) أو الكثير جدا (b)
أقل).
3 مرشح N
:
أ) استخدام N
لذلك عند التحويل من النصdouble
- نتصل وصلنا إلى نفس النص للجميع double
.
std::cout << dbl::digits10 << '\n';
// Typical output
15
ب) استخدام N
لذلك عند التحويل من double
-نص-double
وصلنا إلى نفسه double
للجميع double
.
// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17
متي max_digits10
غير متوفر، لاحظ أنه بسبب قاعدة 2 و 10 سمات 10، digits10 + 2 <= max_digits10 <= digits10 + 3
, ، يمكننا ان نستخدم digits10 + 3
لضمان ما يكفي من الأرقام العشرية المطبوعة.
ج) استخدام N
هذا يختلف مع القيمة.
قد يكون هذا مفيدا عندما يريد التعليمات البرمجية عرض النص الأدنى (N == 1
) أو ال بالضبط قيمة أ double
(N == 1000-ish
في حالة ما اذا denorm_min
). ومع ذلك، لأن هذا هو "العمل" وليس هدف OP المرجح، فسيتم تخصيصه جانبا.
عادة ما يكون ب) يستخدم "طباعة أ 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
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 :: الدقة (int)
cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;
سوف تسفر
3.141592653589793, 2.718281828459045
لماذا عليك أن تقول "+1" ليس لدي أدنى فكرة، لكن الرقم الإضافي الذي تخرج منه هو الصحيح.