Więc otrzymałem odpowiedź na moje ostatnie pytanie (nie wiem, dlaczego o tym nie pomyślałem). Drukowałem double
użycie, cout
które zaokrągliło się, gdy się nie spodziewałem. Jak mogę sprawić, by cout
wydruk był w double
pełni precyzyjny?
331
fixed
? Zdouble h = 6.62606957e-34;
,fixed
daje mi0.000000000000000
iscientific
wychodzi6.626069570000000e-34
.cout.precision(numeric_limits<double>::digits10 + 2);
dostaję tylko 16 ....max_digits10
to samo. Naprawiono odpowiedź, aby to odzwierciedlić.Posługiwać się
std::setprecision
:źródło
std::setprecision (17)
podwójny, zobacz komentarze do odpowiedzi @Bill The Lizard.Oto czego bym użył:
Zasadniczo pakiet limitów ma cechy wszystkich typów wbudowanych.
Jedną z cech liczb zmiennoprzecinkowych (liczba zmiennoprzecinkowa / podwójna / długa podwójna) jest atrybut digits10. To określa dokładność (nie pamiętam dokładnej terminologii) liczby zmiennoprzecinkowej w podstawie 10.
Zobacz: http://www.cplusplus.com/reference/std/limits/numeric_limits.html
Szczegółowe informacje na temat innych atrybutów.
źródło
std::setprecision()
:#include <iomanip>
std::numeric_limits<double>
zamiastnumberic_limits<double>
1
dostd::numeric_limits<double>::digits10
?max_digits10
. Zobacz to .max_digits10
, a nie dowolnedigits10+2
. W przeciwnym razie, w przypadkufloat
,long double
,boost::multiprecision::float128
to nie uda, ponieważ należałoby+3
zamiast+2
.Sposób iostreams jest trochę niezgrabny. Wolę używać,
boost::lexical_cast
ponieważ oblicza dla mnie odpowiednią precyzję. I to też jest szybkie .Wynik:
źródło
Przez pełną precyzję zakładam, że oznacza wystarczającą precyzję, aby pokazać najlepsze przybliżenie do zamierzonej wartości, ale należy zauważyć, że
double
jest przechowywana przy użyciu reprezentacji podstawy 2, a podstawa 2 nie może reprezentować czegoś tak trywialnego jak1.1
dokładnie. Jedynym sposobem na uzyskanie pełnej precyzji rzeczywistego podwójnego (bez BŁĘDU WYŁĄCZENIA ZAOKRĄGLENIA) jest wydrukowanie bitów binarnych (lub hex nybbles). Jednym ze sposobów jest zapisanie wartości „double
a”,union
a następnie wydrukowanie wartości całkowitej bitów.To da ci 100% dokładną precyzję podwójnego ... i będzie całkowicie nieczytelny, ponieważ ludzie nie potrafią odczytać podwójnego formatu IEEE! Wikipedia dobrze napisała, jak interpretować binarne bity.
W nowszym C ++ możesz to zrobić
źródło
Oto jak wyświetlić podwójnie z pełną precyzją:
Wyświetla to:
max_digits10 to liczba cyfr niezbędnych do jednoznacznego przedstawienia wszystkich wyraźnych podwójnych wartości. max_digits10 reprezentuje liczbę cyfr przed i po przecinku.
Nie używaj set_precision (max_digits10) ze std :: fixed.
W stałej notacji set_precision () ustawia liczbę cyfr tylko po przecinku. Jest to niepoprawne, ponieważ max_digits10 reprezentuje liczbę cyfr przed kropką dziesiętną i po niej.
Wyświetla niepoprawny wynik:
Uwaga: Wymagane pliki nagłówka
źródło
100.0000000000005
nie jest reprezentowane dokładnie jakodouble
. (Może się wydawać, że tak powinno być, ale tak nie jest, ponieważ ulega normalizacji , tj. Reprezentacji binarnej). Aby to zobaczyć, spróbuj:100.0000000000005 - 100
. Dostajemy4.973799150320701e-13
.Użyj
hexfloat
lubużyj
scientific
i ustaw dokładnośćZbyt wiele odpowiedzi dotyczy tylko jednej z 1) bazy 2) stałego / naukowego układu lub 3) precyzji. Zbyt wiele precyzyjnych odpowiedzi nie zapewnia odpowiedniej wymaganej wartości. Stąd odpowiedź na stare pytanie.
A
double
jest z pewnością zakodowane przy użyciu bazy 2. Bezpośrednim podejściem w C ++ 11 jest drukowanie przy użyciustd::hexfloat
.Jeśli wyjście nie dziesiętne jest dopuszczalne, jesteśmy skończeni.
fixed
lubscientific
?A
double
jest typem zmiennoprzecinkowym , a nie stałym .Czy nie używać
std::fixed
jako że nie drukować małedouble
jak bynajmniej0.000...000
. W przypadku dużychdouble
drukuje wiele cyfr, być może setki wątpliwej informatywności.Aby drukować z pełną precyzją, najpierw użyj,
std::scientific
który „zapisze wartości zmiennoprzecinkowe w notacji naukowej”. Zauważ, że domyślnie 6 cyfr po przecinku, niewystarczająca ilość, jest obsługiwane w następnym punkcie.ZA
double
Zakodowane przy użyciu bazowej binarnych 2 koduje sama precyzja pomiędzy różnymi uprawnieniami od 2. Jest to często 53 bitów.[1,0 ... 2,0) są 2 53 różne
double
,[2,0 ... 4,0) są 2 53 różne
double
,[4,0 ... 8,0) są 2 53 różne
double
,[8,0 ... 10,0) są 2 / 8 * 2 53 różne
double
.Jednak jeśli kod jest drukowany w systemie dziesiętnym z
N
cyframi znaczącymi, liczba kombinacji [1,0 ... 10,0) wynosi 9/10 * 10 N. .Bez względu na
N
wybraną (precyzję)double
tekst nie będzie mapowany jeden na jeden między tekstem dziesiętnym a dziesiętnym. JeśliN
zostanie wybrana wartość stała , czasami będzie ona nieco bardziej lub mniej niż rzeczywiście potrzebna dla niektórychdouble
wartości. Możemy popełnić błąd na zbyt małej (a)
poniżej) lub zbyt dużej (b)
poniżej).3 kandydatów
N
:a) Użyj
N
so podczas konwersji zdouble
tekstu-tekstu, aby uzyskać ten sam tekst dla wszystkichdouble
.b) Użyj
N
so podczas konwersji zdouble
-tekstu -double
my osiągamy to samodouble
dla wszystkichdouble
.Gdy
max_digits10
nie jest dostępny, należy pamiętać, że ze względu na atrybuty base 2 i base 10digits10 + 2 <= max_digits10 <= digits10 + 3
możemy użyćdigits10 + 3
aby zapewnić wydrukowanie wystarczającej liczby cyfr dziesiętnych.c) Użyj
N
zmiennej zależnej od wartości.Może to być przydatne, gdy kod chce wyświetlać minimalny tekst (
N == 1
) lub dokładną wartość wartość adouble
(N == 1000-ish
w przypadkudenorm_min
). Ponieważ jednak jest to „praca” i mało prawdopodobny cel PO, zostanie on odłożony na bok.Zwykle jest to b) używane do „wydrukowania a
double
wartości z pełną precyzją”. Niektóre aplikacje mogą preferować: a) błąd przy niedostarczeniu zbyt dużej ilości informacji.Z
.scientific
,.precision()
zestawy liczba cyfr do wydrukowania po przecinku, więc1 + .precision()
cyfry są drukowane. Kod potrzebujemax_digits10
więc cyfr całkowitych.precision()
jest nazywany za pomocąmax_digits10 - 1
.Podobne pytanie C.
źródło
precision()
określa liczbę miejsc po przecinku dla trybu naukowego. Bez określaniascientific
określa całkowitą liczbę cyfr, z wyłączeniem wykładnika wykładniczego. Wciąż możesz uzyskać wyniki naukowe, w zależności od wartości liczbowej, ale wtedy możesz również otrzymać mniej cyfr niż podałeś. Przykład:cout.precision(3); cout << 1.7976931348623158e+308; // "1.8e+308"
wyniki dlaprintf
mogą być inne. Mylące rzeczy, o których należy pamiętać.char buf[DBL_DECIMAL_DIG + 3 + 5]; sprintf(buf, "%.*g", DBL_DECIMAL_DIG, d);
Dodatkowe znaki to: znak, kropka dziesiętna, końcowe zero, e [+ | -], 3 cyfry wykładnika ( DBL_MAX_10_EXP = 308). Stąd całkowita liczba wymaganych znaków wynosi 25.% .12f oznacza zmiennoprzecinkowy, z dokładnością do 12 cyfr.
źródło
Najbardziej przenośny ...
źródło
Z ostream :: precyzja (int)
ustąpi
Dlaczego musisz powiedzieć „+1” Nie mam pojęcia, ale dodatkowa cyfra, którą z niej wyciągasz, jest poprawna.
źródło
Spowoduje to wyświetlenie wartości do dwóch miejsc po przecinku po kropce.
Zobacz tutaj: Notacja punktu stałego
std :: naprawiono
std :: setprecision
Jeśli znasz standard IEEE do przedstawiania liczb zmiennoprzecinkowych, wiedziałbyś, że niemożliwe jest pokazanie zmiennoprzecinkowych z pełną precyzją poza zakresem normy , to znaczy zawsze spowoduje to zaokrąglenie wartości rzeczywistej.
Najpierw musisz sprawdzić, czy wartość mieści się w zakresie , jeśli tak, to użyj:
std :: defaultfloat
Jest to również domyślne zachowanie
cout
, co oznacza, że nie używasz go jawnie.źródło