Son sorumun cevabını aldım (neden böyle düşünmediğimi bilmiyorum). Bir basıyordum doublekullanarak coutbunu beklemiyordum zaman anladınız yuvarlanır. Nasıl coutbaskı yapabilirimdoubleTam hassasiyet kullanarak ?
Son sorumun cevabını aldım (neden böyle düşünmediğimi bilmiyorum). Bir basıyordum doublekullanarak coutbunu beklemiyordum zaman anladınız yuvarlanır. Nasıl coutbaskı yapabilirimdoubleTam hassasiyet kullanarak ?
Yanıtlar:
Hassasiyeti doğrudan ayarlayabilir std::coutve std::fixedformat belirleyiciyi kullanabilirsiniz .
double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;
#include <limits>Bir şamandıra veya çiftin maksimum hassasiyetini elde edebilirsiniz .
#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);sadece 16'yı alıyorum ....
max_digits10 aynısını göstermek için tanıtıldı . Yanıtın bunu yansıtması düzeltildi.
Kullanım std::setprecision:
std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;
std::setprecision (17)çift için, @Bill Lizard'ın cevap yorumlara bakınız.
İşte ne kullanacağım:
std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
<< 3.14159265358979
<< std::endl;
Temel olarak sınırlar paketi, tüm yapı türleri için özelliklere sahiptir.
Kayan nokta sayılarının özelliklerinden biri (float / double / long double) digits10 özelliğidir. Bu, taban 10'daki bir kayan nokta sayısının doğruluğunu (kesin terminolojiyi unutuyorum) tanımlar.
Bkz. Http://www.cplusplus.com/reference/std/limits/numeric_limits.html
Diğer özellikler hakkında ayrıntılar için.
std::setprecision(): #include <iomanip>
std::numeric_limits<double>yerine olmalınumberic_limits<double>
1için std::numeric_limits<double>::digits10?
max_digits10, keyfi değil digits10+2. Aksi takdirde, söz konusu float, long double, boost::multiprecision::float128, gerekir orada beri bu, başarısız olacaktır +3yerine +2.
İostreams yolu biraz tıknaz. Kullanmayı tercih ederim boost::lexical_castçünkü benim için doğru hassasiyeti hesaplıyor. Ve hızlı da.
#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;
Çıktı:
Pi: 3.14159265358979
Tam hassasiyetle, amaçlanan değere en iyi yaklaşımı gösterecek kadar hassas olduğunu varsayıyorum, ancak doublebaz 2 temsili kullanılarak saklanan ve baz 2'nin 1.1tam olarak önemsiz bir şeyi temsil edemeyeceği belirtilmelidir . Gerçek çiftin tam hassasiyetini elde etmenin tek yolu (YUVARLAK KAPALI HATALI), ikili bitleri (veya altıgen nybbles) yazdırmaktır. Bunu yapmanın bir yolu, yazıyor doublebir etmek unionve daha sonra bit tamsayı değeri yazdırmak.
union {
double d;
uint64_t u64;
} x;
x.d = 1.1;
std::cout << std::hex << x.u64;
Bu size çiftin% 100 doğru hassasiyetini verecektir ... ve tamamen okunamaz olacaktır çünkü insanlar IEEE çift formatını okuyamaz! Wikipedia , ikili bitlerin nasıl yorumlanacağı konusunda iyi bir yazıya sahiptir.
Daha yeni C ++ 'da şunları yapabilirsiniz:
std::cout << std::hexfloat << 1.1;
Bir çiftin tam hassasiyetle nasıl gösterileceği aşağıda açıklanmıştır:
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;
Bu görüntülenir:
100,0000000000005
max_digits10, tüm farklı çift değerleri benzersiz bir şekilde temsil etmek için gereken basamak sayısıdır. max_digits10, ondalık basamaktan önceki ve sonraki basamak sayısını temsil eder.
Std :: fixed ile set_precision (max_digits10) kullanmayın.
Sabit gösterimde, set_precision () yalnızca ondalık noktadan sonraki basamak sayısını ayarlar . Max_digits10 , ondalık noktadan önceki ve sonraki basamak sayısını temsil ettiğinden bu yanlıştır .
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;
Bu yanlış sonuç gösteriyor:
100,00000000000049738
Not: Başlık dosyaları gerekir
#include <iomanip>
#include <limits>
100.0000000000005, tam olarak bir olarak gösterilmediği için olur double. (Olması gerektiği gibi görünebilir, ancak normalleşmez , yani ikili temsili). Bunu görmek için, deneyin: 100.0000000000005 - 100. Anlıyoruz 4.973799150320701e-13.
Bir
doubledeğeri cout kullanarak tam hassasiyetle nasıl yazdırabilirim ?
Hassasiyeti kullanın hexfloatveya
kullanın scientificve ayarlayın
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
Çok fazla cevap 1) temel 2) sabit / bilimsel düzen veya 3) hassasiyetten sadece birini ele almaktadır. Hassaslıkla çok fazla cevap gerekli olan uygun değeri sağlamaz. Bu yüzden eski bir sorunun cevabı.
A doublekesinlikle taban 2 kullanılarak kodlanır. C ++ 11 ile doğrudan bir yaklaşım kullanarak yazdırmaktır std::hexfloat.
Ondalık olmayan bir çıktı kabul edilebilirse, işimiz bitmiştir.
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
fixedveya scientific?A double, kayan nokta tipidir, sabit nokta değildir .
Do not kullanmak std::fixedbu küçük yazdırmak için başarısız olarak doublebir şey ama 0.000...000. Büyük için double, birçok basamak, belki de yüzlerce şüpheli bilgilendirme basar .
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
Tam hassasiyetle yazdırmak için ilk önce std::scientific"bilimsel gösterimde kayan nokta değerleri yazacak" kullanın. Ondalık noktadan sonraki 6 basamaklı varsayılan değerin, yetersiz bir miktarın bir sonraki noktada ele alındığına dikkat edin.
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
Bir doubleikili tabanı 2 kodlamakta Bu genellikle 53 bit 2. çeşitli güçler arasında aynı hassas kullanılarak kodlanır.
[1.0 ... 2.0) 2 53 farklı double,
[2.0 ... 4.0) 2 53 farklı double,
[4.0 ... 8.0) 2 53 farklı double,
[8.0 ... 10.0) 2 / 8 * 2 53 farklı double.
Yine de, kod Nönemli basamaklarla ondalık olarak yazdırılıyorsa , kombinasyon sayısı [1.0 ... 10.0) 9/10 * 10 N'dir .
NSeçilen (kesinlik) ne olursa olsun , doubleondalık metin arasında bire bir eşleme olmaz . Bir sabit Nseçilirse, bazen belirli doubledeğerler için gerçekten gerekenden biraz daha fazla veya daha az olacaktır . Çok az ( a)aşağıda) veya çok fazla ( aşağıda) hata verebiliriz b).
3 aday N:
a) Metin-metinden Ndönüştürürken doubleherkes için aynı metne ulaştığımız şekilde bunu kullanın double.
std::cout << dbl::digits10 << '\n';
// Typical output
15
b) bir kullanma Ndönüştürürken çok double-text- doubleaynı varmak doubleiçin tüm double.
// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17
Ne zaman max_digits10mevcut değildir nedeniyle tabanın 2 ve baz 10 özelliklerine, o notu digits10 + 2 <= max_digits10 <= digits10 + 3, kullanabileceğimiz digits10 + 3yeterli ondalık basamak sigorta yazdırılır.
c) Değere Ngöre değişen bir kullanın .
Bu, kod en az metni ( N == 1) veya tam bir değeri double( N == 1000-ishdurumunda denorm_min). Ancak bu “iş” olduğu ve muhtemelen OP'nin hedefi olmadığı için bir kenara bırakılacaktır.
Genellikle b) " doubledeğeri tam hassasiyetle basmak" için kullanılır . Bazı uygulamalar a) çok fazla bilgi vermemede hata yapmayı tercih edebilir.
İle .scientific, .precision()ondalık noktadan sonra yazdırılacak basamak sayısını ayarlar, böylece 1 + .precision()basamaklar yazdırılır. Kodun max_digits10toplam basamağa ihtiyacı var,.precision() , ile çağrılır 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()Bilimsel mod için ondalık basamak sayısını belirleyen haklısınız . Belirtmeden scientific, üs hariç toplam basamak sayısını ayarlar. Sayı değerinize bağlı olarak yine de bilimsel çıktı alabilirsiniz, ancak daha sonra belirttiğinizden daha az hane alabilirsiniz. Örnek: için cout.precision(3); cout << 1.7976931348623158e+308; // "1.8e+308"sonuçlar printffarklı olabilir. Kafa karıştırıcı şeyler farkında olmalıdır.
char buf[DBL_DECIMAL_DIG + 3 + 5]; sprintf(buf, "%.*g", DBL_DECIMAL_DIG, d);Ekstra karakterler şöyledir: işaret, ondalık nokta, arka sıfır, e [+ | -], üs için 3 basamak ( DBL_MAX_10_EXP = 308). Bu nedenle gerekli toplam karakter sayısı 25'tir.
printf("%.12f", M_PI);
% .12f, 12 basamak hassasiyetle kayan nokta anlamına gelir.
En portatif olarak ...
#include <limits>
using std::numeric_limits;
...
cout.precision(numeric_limits<double>::digits10 + 1);
cout << d;
Ostream ile :: duyarlık (int)
cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;
getirecek
3.141592653589793, 2.718281828459045
Neden "+1" demek zorundasınız? Hiçbir fikrim yok, ama bundan elde ettiğiniz ekstra rakam doğrudur.
Bu noktadan sonra iki ondalık basamağa kadar olan değeri gösterecektir.
#include <iostream>
#include <iomanip>
double d = 2.0;
int n = 2;
cout << fixed << setprecison(n) << d;
Buraya bakın: Sabit noktalı gösterim
Sabit kayan nokta gösterimini kullan Str akışı için kayan nokta biçimi bayrağını sabit olarak ayarlar.
Kayan alan sabit olarak ayarlandığında, kayan nokta değerleri sabit nokta gösterimi kullanılarak yazılır: değer, tam olarak ondalık kısımda, kesinlik alanı (kesinlik) tarafından belirtilen sayıda basamak ile temsil edilir ve üs parçası yoktur.
Ondalık duyarlığı ayarlama Çıktı işlemlerinde kayan nokta değerlerini biçimlendirmek için kullanılacak ondalık duyarlığı ayarlar.
Kayan noktaları temsil etmek için IEEE standardını biliyorsanız, standartın kapsamı dışında tam hassasiyetle kayan noktaları göstermenin imkansız olduğunu bilirsiniz , yani her zaman gerçek değerin yuvarlanması.
İlk önce değerin kapsam dahilinde olup olmadığını kontrol etmeniz gerekir , eğer evetse, şunu kullanın:
cout << defaultfloat << d ;
Varsayılan kayan nokta gösterimini kullan str akışı için kayan nokta biçimi bayrağını defaultfloat olarak ayarlar.
Kayan alan varsayılan yüzeye ayarlandığında, kayan nokta değerleri varsayılan gösterim kullanılarak yazılır: gösterim, akışın ondalık duyarlığına (kesinlik) kadar gerektiği kadar çok sayıda anlamlı basamak kullanır ve ondalık noktadan önceki ve sonraki sayıları sayar (varsa) ).
Bu aynı zamanda varsayılan davranışıdır cout, yani açıkça kullanmazsınız.
fixed? İledouble h = 6.62606957e-34;,fixedbana verir0.000000000000000vescientificçıktılar6.626069570000000e-34.