Die Präzision des langen Doppel Ausgangs ist nicht korrekt. Was könnte falsch sein?
-
22-08-2019 - |
Frage
Ich habe eine long double
konstant, dass ich entweder als const oder nicht-const setze. Es ist länger (40 Stellen) als die Präzision eines long double
auf meiner Test-Workstation (19 Stellen).
Wenn ich es ausdrucken, es wird nicht mehr auf 19 Stellen genau angezeigt, aber bei 16.
Hier ist der Code Ich teste:
#include <iostream>
#include <iomanip>
#include <limits>
#include <cstdio>
int main ()
{
const long double constLog2 = 0.6931471805599453094172321214581765680755;
long double log2 = 0.6931471805599453094172321214581765680755;
std::cout << std::numeric_limits<long double>::digits10 + 1 << std::endl;
std::cout << "const via cout: " << std::setprecision(19) << constLog2 << std::endl;
std::cout << "non-const via cout: " << std::setprecision(19) << log2 << std::endl;
std::fprintf(stdout, "const via printf: %.19Lf\n", constLog2);
std::fprintf(stdout, "non-const via printf: %.19Lf\n", log2);
return 0;
}
Übersetzen:
$ g++ -Wall precisionTest.cpp
Ausgabe:
$ ./a.out
19
const via cout: 0.6931471805599452862
non-const via cout: 0.6931471805599452862
const via printf: 0.6931471805599452862
non-const via printf: 0.6931471805599452862
Ich würde 0.6931471805599453094
erwarten, sondern 0.6931471805599452862
erhalten.
Gibt es einen Grund, dass die 19-stelliger Genauigkeit zu 16 Stellen geschnitten werden?
Hier ist meine Umwelt:
$ gcc --version
i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5490)
Ich sehe das gleiche Problem mit anderen Versionen von gcc, z.
$ gcc --version
g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-10)
Blick in NTL oder anderen Bibliotheken ich kann, aber ich bin gespannt, was dies verursacht. Vielen Dank für Ihre Einsicht.
Lösung
ich diese Ausgabe:
19
const via cout: 0.6931471805599453094
non-const via cout: 0.6931471805599453094
const via printf: 0.6931471805599453094
non-const via printf: 0.6931471805599453094
Aber ich bin lange Doppel Literale statt Doppel Literale mit:
const long double constLog2 = 0.6931471805599453094172321214581765680755L;
long double log2 = 0.6931471805599453094172321214581765680755L;
Andere Tipps
Es gibt einige subtilen Fragen im Zusammenhang mit Hardware-Plattformen und kompilieren Optionen, die von Interesse sein könnten:
- https://www.amazon.com/exec/obidos/ASIN/0954161793 / netzwerkforschung-20
- 3.17.3 Intel 386 und AMD x86-64 Optionen (gcc-4.0.1) (archivierten developer.apple.com Dokumentation)
- 3.17.12 Intel 386 und AMD x86-64 Optionen (gcc-4.0.1) (gcc.gnu.org Dokumentation)
Diese '-m‘Optionen sind definiert für die i386 und x86-64-Familie von Computern:
-m96bit-long-double
-m128bit-long-double
Diese Schalter steuern die Größe der langen Doppel Typ. Die i386 Application Binary Interface die Größe spezifiziert 96 Bits zu sein, so -m96bit-long-double ist die Standardeinstellung in 32-Bit-Modus. moderne Architekturen (Pentium und neuere) würde es vorziehen, lange doppelt auf einen 8 oder 16 ausgerichtet werden, Byte-Grenze. In Arrays oder Strukturen mit dem ABI konforme, würde dies nicht möglich sein. So spezifiziert ein -m128bit-long-Doppel wird long double zu einer Grenze 16-Byte-ausgerichtet, indem Klotzen des long double mit einem zusätzliche 32-Bit-Null.
In dem x86-64-Compiler, -m128bit-long-double ist die Standardeinstellung als ABI, dass lange spezifiziert Doppel ist auf 16-Byte-ausgerichtet werden, Grenze.
Beachten Sie, dass keine dieser Optionen ermöglichen jede zusätzliche Präzision über die x87-Standard von 80 Bits für eine lange doppelt.
Achtung: Wenn Sie die Standardeinstellung überschreiben Wert für Ihr Ziel ABI, die Strukturen und Anordnungen, enthaltend lange Doppel Variablen ihre ändern Größe sowie Funktionsaufruf Konvention für die Funktion nehmen lange Doppel wird modifiziert werden. daher sie nicht binär kompatibel mit Arrays oder Strukturen in Code kompiliert ohne diesen Schalter.