Jadi saya mendapatkan jawaban untuk pertanyaan terakhir saya (saya tidak tahu mengapa saya tidak memikirkan itu). Saya mencetak double
menggunakan cout
yang bulat ketika saya tidak mengharapkannya. Bagaimana saya bisa membuat cout
cetakan double
menggunakan presisi penuh?
332
fixed
? Dengandouble h = 6.62606957e-34;
,fixed
beri saya0.000000000000000
danscientific
output6.626069570000000e-34
.cout.precision(numeric_limits<double>::digits10 + 2);
saya hanya mendapatkan 16 ....max_digits10
untuk menunjukkan hal yang sama. Memperbaiki jawaban untuk mencerminkan hal ini.Gunakan
std::setprecision
:sumber
std::setprecision (17)
ganda, lihat komentar di @Bill The Lizard's answer.Inilah yang akan saya gunakan:
Pada dasarnya paket limit memiliki ciri untuk semua tipe build.
Salah satu ciri untuk angka floating point (float / double / long double) adalah atribut digits10. Ini mendefinisikan keakuratan (saya lupa terminologi yang tepat) dari angka floating point di basis 10.
Lihat: http://www.cplusplus.com/reference/std/limits/numeric_limits.html
Untuk detail tentang atribut lainnya.
sumber
std::setprecision()
:#include <iomanip>
std::numeric_limits<double>
bukannumberic_limits<double>
1
kestd::numeric_limits<double>::digits10
?max_digits10
sebagai gantinya. Lihat ini .max_digits10
, tidak ada yang sewenang-wenangdigits10+2
. Jika tidak, dalam kasusfloat
,long double
,boost::multiprecision::float128
ini akan gagal, karena di sana Anda akan perlu+3
bukan+2
.Cara iostreams agak kikuk. Saya lebih suka menggunakan
boost::lexical_cast
karena menghitung presisi yang tepat untuk saya. Dan juga cepat .Keluaran:
sumber
Dengan presisi penuh, saya mengasumsikan presisi yang cukup berarti untuk menunjukkan perkiraan terbaik dengan nilai yang dimaksudkan, tetapi harus ditunjukkan bahwa
double
disimpan menggunakan representasi basis 2 dan basis 2 tidak dapat mewakili sesuatu yang sepele seperti1.1
tepatnya. Satu-satunya cara untuk mendapatkan presisi penuh-penuh dari dobel yang sebenarnya (dengan NO ROUND OFF ERROR) adalah dengan mencetak bit biner (atau hexbuster). Salah satu cara melakukannya adalah menulisdouble
ke aunion
dan kemudian mencetak nilai integer bit.Ini akan memberi Anda presisi akurat 100% dari ganda ... dan benar-benar tidak dapat dibaca karena manusia tidak dapat membaca format ganda IEEE! Wikipedia memiliki tulisan yang bagus tentang cara menafsirkan bit biner.
Di C ++ yang lebih baru, Anda bisa melakukannya
sumber
Berikut ini cara menampilkan ganda dengan presisi penuh:
Ini menampilkan:
max_digits10 adalah jumlah digit yang diperlukan untuk secara unik mewakili semua nilai ganda yang berbeda. max_digits10 menunjukkan jumlah digit sebelum dan sesudah titik desimal.
Jangan gunakan set_precision (max_digits10) dengan std :: fix.
Pada notasi tetap, set_precision () menetapkan jumlah digit hanya setelah titik desimal. Ini tidak benar karena max_digits10 mewakili jumlah digit sebelum dan sesudah titik desimal.
Ini menampilkan hasil yang salah:
Catatan: Diperlukan file tajuk
sumber
100.0000000000005
tidak direpresentasikan secara tepat sebagai adouble
. (Ini mungkin tampak seperti seharusnya, tetapi tidak, karena menjadi dinormalisasi , yaitu representasi binernya). Untuk melihat ini, coba:100.0000000000005 - 100
. Kami mendapatkan4.973799150320701e-13
.Gunakan
hexfloat
ataugunakan
scientific
dan atur presisiTerlalu banyak jawaban hanya membahas satu dari 1) basis 2) tata letak tetap / ilmiah atau 3) presisi. Terlalu banyak jawaban dengan presisi tidak memberikan nilai tepat yang dibutuhkan. Karena itu, ini menjawab pertanyaan lama.
A
double
tentu dikodekan menggunakan basis 2. Pendekatan langsung dengan C ++ 11 adalah mencetak menggunakanstd::hexfloat
.Jika output non-desimal dapat diterima, kita selesai.
fixed
atauscientific
?A
double
adalah tipe titik mengambang , bukan titik tetap .Jangan tidak menggunakan
std::fixed
sebagai yang gagal untuk mencetak kecildouble
sebagai sesuatu tetapi0.000...000
. Secara umumdouble
, ia mencetak banyak digit, mungkin ratusan informasi yang dipertanyakan.Untuk mencetak dengan presisi penuh, gunakan pertama
std::scientific
yang akan "menulis nilai floating-point dalam notasi ilmiah". Perhatikan default 6 digit setelah titik desimal, jumlah yang tidak mencukupi, ditangani di titik berikutnya.A
double
dikodekan menggunakan basis biner 2 mengkodekan presisi yang sama antara berbagai kekuatan 2. Ini sering 53 bit.[1.0 ... 2.0) ada 2 53 berbeda
double
,[2.0 ... 4.0) ada 2 53 berbeda
double
,[4.0 ... 8.0) ada 2 53 berbeda
double
,[8.0 ... 10.0) ada 2 / 8 * 2 53 berbeda
double
.Namun jika kode cetakan dalam desimal dengan
N
angka yang signifikan, jumlah kombinasi [1.0 ... 10.0) adalah 9/10 * 10 N .Apa pun
N
(presisi) yang dipilih, tidak akan ada pemetaan satu-ke-satu antaradouble
dan teks desimal. Jika fixN
dipilih, kadang-kadang akan sedikit lebih atau kurang dari yang dibutuhkan untukdouble
nilai - nilai tertentu . Kami dapat kesalahan pada terlalu sedikit (dia)
bawah) atau terlalu banyak (dib)
bawah).3 kandidat
N
:a) Gunakan
N
jadi ketika mengkonversi dari teks-double
-teks kita tiba di teks yang sama untuk semuadouble
.b) Gunakan
N
jadi ketika mengkonversi daridouble
-text-double
kita tiba di samadouble
untuk semuadouble
.Ketika
max_digits10
tidak tersedia, perhatikan bahwa karena atribut basis 2 dan basis 10digits10 + 2 <= max_digits10 <= digits10 + 3
,, kita dapat menggunakandigits10 + 3
untuk memastikan angka desimal yang cukup dicetak.c) Gunakan an
N
yang bervariasi dengan nilainya.Ini bisa bermanfaat ketika kode ingin menampilkan teks minimal (
N == 1
) atau nilai tepat adouble
(N == 1000-ish
untuk kasusdenorm_min
). Namun karena ini "bekerja" dan bukan tujuan OP, itu akan dikesampingkan.Biasanya b) yang digunakan untuk "mencetak
double
nilai dengan presisi penuh". Beberapa aplikasi mungkin lebih suka a) salah karena tidak memberikan terlalu banyak informasi.Dengan
.scientific
,.precision()
atur jumlah digit untuk dicetak setelah titik desimal, sehingga1 + .precision()
digit dicetak. Kode membutuhkanmax_digits10
angka total sehingga.precision()
disebut dengan amax_digits10 - 1
.Pertanyaan C serupa
sumber
precision()
menetapkan jumlah tempat desimal untuk mode ilmiah. Tanpa menentukanscientific
, itu menetapkan jumlah digit, tidak termasuk eksponen. Anda mungkin masih berakhir dengan hasil ilmiah, tergantung pada nilai angka Anda, tetapi kemudian Anda mungkin juga mendapatkan lebih sedikit digit dari yang Anda tentukan. Contoh:cout.precision(3); cout << 1.7976931348623158e+308; // "1.8e+308"
Hasil untukprintf
mungkin berbeda. Hal-hal membingungkan yang harus disadari.char buf[DBL_DECIMAL_DIG + 3 + 5]; sprintf(buf, "%.*g", DBL_DECIMAL_DIG, d);
Karakter tambahan untuk: tanda, titik desimal, trailing nol, e [+ | -], 3 digit untuk eksponen ( DBL_MAX_10_EXP = 308). Karenanya jumlah total karakter yang diperlukan adalah 25.% .12f berarti titik mengambang, dengan presisi 12 digit.
sumber
Paling nyaman ...
sumber
Dengan ostream :: presisi (int)
akan menghasilkan
Mengapa Anda harus mengatakan "+1" Saya tidak tahu, tetapi digit tambahan yang Anda dapatkan dari itu benar.
sumber
Ini akan menunjukkan nilai hingga dua tempat desimal setelah titik.
Lihat di sini: Notasi titik tetap
std :: diperbaiki
std :: setprecision
Jika Anda terbiasa dengan standar IEEE untuk mewakili floating-point, Anda akan tahu bahwa tidak mungkin untuk menunjukkan floating-point dengan presisi penuh di luar ruang lingkup standar , yaitu, itu akan selalu menghasilkan pembulatan dari nilai sebenarnya.
Anda harus terlebih dahulu memeriksa apakah nilainya dalam cakupan , jika ya, gunakan:
std :: defaultfloat
Itu juga merupakan perilaku default
cout
, yang berarti Anda tidak menggunakannya secara eksplisit.sumber