0,1 Float ist größer als 0,1 Double. Ich hatte erwartet, dass es falsch ist [duplicate]
Lesezeit: 5 Minuten
Hesham Eraqi
Lassen:
double d = 0.1;
float f = 0.1;
sollte der Ausdruck
(f > d)
Rückkehr true oder false?
Empirisch lautet die Antwort true. Allerdings habe ich damit gerechnet false.
Wie 0.1 kann nicht perfekt binär dargestellt werden, während Double dies getan hat 15 zu 16 Dezimalstellen der Genauigkeit und Float hat nur 7. Sie sind also beide kleiner als 0.1während das Doppel näher dran ist 0.1.
Ich brauche eine genaue Erklärung für die true.
Weniger Präzision bedeutet nicht weniger Anzahl.
– Zakinster
10. Oktober 2013 um 9:43 Uhr
Warum hast du das Gegenteil erwartet?
– Benutzer207421
10. Oktober 2013 um 9:47 Uhr
Die einzige gegebene Sache ist, dass die doppelte Genauigkeit dem gewünschten Wert NÄHER ist. Es könnte kleiner sein, es könnte größer sein.
Angenommen, Sie berechnen 1/9 in 3-stelliger Dezimalzahl und 6-stelliger Dezimalzahl. 0.111 < 0.111111, Rechts? Angenommen, Sie berechnen 6/9. 0.667 > 0.666667, Rechts? Sie können es nicht haben, dass 6/9 eine dreistellige Dezimalzahl ist 0.666 denn das ist nicht die nächste 3-stellige Dezimalzahl zu 6/9!
– Eric Lippert
10. Oktober 2013 um 13:26 Uhr
kennytm
Ich würde sagen, die Antwort hängt vom Rundungsmodus beim Konvertieren ab double zu float. float hat 24 binär Bits von Präzision und double hat 53. Binär ist 0,1:
Wenn wir also runden hoch an der 24. Stelle bekommen wir
0.1₁₀ ~ 0.000110011001100110011001101
was größer ist als der genaue Wert und die genauere Näherung bei 53 Stellen.
präzise antwort…!
– Barath Ravikumar
10. Oktober 2013 um 9:48 Uhr
Logische Erklärung. Was denkst du aber über Svens Antwort?
– Hescham Eraqi
10. Oktober 2013 um 10:21 Uhr
mit anderen Worten 0.2d > 0.2f
– Ratschenfreak
10. Oktober 2013 um 12:27 Uhr
@ratchetfreak … oder nicht … hängt davon ab, ob die Sprache IEEE 754 implementiert, auf welcher Plattform sie ausgeführt wird …
– woliveirajr
10. Oktober 2013 um 12:29 Uhr
@HeshamERAQI Beide Antworten sind richtig – ich denke, diese macht es einfacher zu sehen warum das passiert. Bei beiden Erklärungen ist es jedoch entscheidend zu berücksichtigen, wie das Ergebnis an der Trennstelle gerundet wird. Wie andere Kommentare bereits gesagt haben, macht IEEE754, der De-facto-Standard für FP-Darstellungen, dies auf diese Weise, aber theoretisch könnte es FP-Implementierungen geben, die einfach abschneiden, anstatt zu runden.
– us2012
10. Oktober 2013 um 14:18 Uhr
Sven Marnach
Die Zahl 0,1 wird auf die nächste Fließkommadarstellung mit der angegebenen Genauigkeit gerundet. Diese Annäherung kann entweder größer oder kleiner als 0,1 sein, sodass Sie ohne Betrachtung der tatsächlichen Werte nicht vorhersagen können, ob die Annäherung mit einfacher oder doppelter Genauigkeit größer ist.
Hier ist, worauf der Wert mit doppelter Genauigkeit gerundet wird (mithilfe eines Python-Interpreters):
Sie können also sehen, dass die Annäherung mit einfacher Genauigkeit größer ist.
Dies hängt jedoch von der Implementierung ab. Ich vermute, dass Ihre Ergebnisse für IEEE sind double und floatda dies heute bei weitem am häufigsten verwendet wird, aber auf einem IBM- oder Unisys-Mainframe erhalten Sie möglicherweise andere Ergebnisse.
– James Kanze
10. Oktober 2013 um 9:56 Uhr
@JamesKanze: Dies ist auf einem x86-Computer. Python verwendet native Gleitkommaoperationen, und die x86-Implementierung entspricht (mehr oder weniger) IEEE-754.
– Sven Marnach
10. Oktober 2013 um 10:03 Uhr
Das habe ich mehr oder weniger angenommen (zumindest IEEE-745): Ich denke, fast alle Maschinen, für die Python implementiert ist, verwenden IEEE-754. Mein Punkt ist nur, dass die entsprechenden Werte auf einer anderen Architektur (wie einigen Mainframes, die kein IEEE verwenden) unterschiedlich sein können.
Der Titel Ihrer eingefärbten Seite gibt einen Schluss, also habe ich das in Ihren Link eingefügt.
– Grijesh Chauhan
11. Oktober 2013 um 11:31 Uhr
Ich denke, Eric Lipperts Kommentar zu der Frage ist eigentlich die klarste Erklärung, also werde ich ihn als Antwort erneut posten:
Angenommen, Sie berechnen 1/9 in 3-stelliger Dezimalzahl und 6-stelliger Dezimalzahl. 0,111 < 0,111111, richtig?
Angenommen, Sie berechnen 6/9. 0,667 > 0,666667, richtig?
Sie können es nicht haben, dass 6/9 in dreistelliger Dezimalzahl 0,666 ist, weil das nicht die nächste 3-stellige Dezimalzahl zu 6/9 ist!
Da es nicht genau dargestellt werden kann, ist der Vergleich von 1/10 zur Basis 2 wie der Vergleich von 1/7 zur Basis 10.
1/7 = 0,142857142857 … aber ein Vergleich bei unterschiedlichen Genauigkeiten zur Basis 10 (3 gegenüber 6 Dezimalstellen) ergibt 0,143 > 0,142857.
BlueRaja – Danny Pflughöft
Nur um die anderen Antworten zu ergänzen, die über IEEE-754 und x86 sprechen: Das Problem ist noch komplizierter, als es scheint. Es gibt nicht “eine” Darstellung von 0,1 in IEEE-754 – es gibt zwei. Entweder das Abrunden der letzten Ziffer nach unten oder nach oben wäre gültig. Dieser Unterschied kann und kommt tatsächlich vorweil x86 dies tut nicht 64-Bit für seine internen Gleitkommaberechnungen verwenden; es verwendet tatsächlich 80-Bit! Das nennt man doppelte erweiterte Genauigkeit.
So kommt es selbst bei reinen x86-Compilern manchmal vor, dass dieselbe Zahl auf zwei verschiedene Arten dargestellt wird, da einige ihre binäre Darstellung mit 64-Bit berechnen, während andere 80 verwenden.
Tatsächlich kann es sogar mit demselben Compiler passieren, sogar auf derselben Maschine!
#include <iostream>
#include <cmath>
void foo(double x, double y)
{
if (std::cos(x) != std::cos(y)) {
std::cout << "Huh?!?\n"; //← you might end up here when x == y!!
}
}
int main()
{
foo(1.0, 1.0);
return 0;
}
Der Rang von Double ist größer als der von Float bei Konvertierungen. Durch einen logischen Vergleich wird f in Double umgewandelt und möglicherweise liefert die von Ihnen verwendete Implementierung inkonsistente Ergebnisse. Wenn Sie f anhängen, damit der Compiler es als Float registriert, erhalten Sie 0,00, was im Double-Typ falsch ist. Fließende Typen ohne Suffix sind doppelt.
#include <stdio.h>
#include <float.h>
int main()
{
double d = 0.1;
float f = 0.1f;
printf("%f\n", (f > d));
return 0;
}
14210700cookie-check0,1 Float ist größer als 0,1 Double. Ich hatte erwartet, dass es falsch ist [duplicate]yes
Weniger Präzision bedeutet nicht weniger Anzahl.
– Zakinster
10. Oktober 2013 um 9:43 Uhr
Warum hast du das Gegenteil erwartet?
– Benutzer207421
10. Oktober 2013 um 9:47 Uhr
Die einzige gegebene Sache ist, dass die doppelte Genauigkeit dem gewünschten Wert NÄHER ist. Es könnte kleiner sein, es könnte größer sein.
– SinisterMJ
10. Oktober 2013 um 11:27 Uhr
@heshameraqi: Die Antworten (insbesondere die von Kenny) sind großartig, um zu zeigen, was passiert. Ich glaube, Sie könnten davon profitieren, wenn Sie Folgendes lesen: Was jeder Informatiker über Gleitkommaarithmetik wissen sollte
– Olivier Dulac
10. Oktober 2013 um 12:58 Uhr
Angenommen, Sie berechnen 1/9 in 3-stelliger Dezimalzahl und 6-stelliger Dezimalzahl.
0.111 < 0.111111
, Rechts? Angenommen, Sie berechnen 6/9.0.667 > 0.666667
, Rechts? Sie können es nicht haben, dass 6/9 eine dreistellige Dezimalzahl ist0.666
denn das ist nicht die nächste 3-stellige Dezimalzahl zu 6/9!– Eric Lippert
10. Oktober 2013 um 13:26 Uhr