0,1 Float ist größer als 0,1 Double. Ich hatte erwartet, dass es falsch ist [duplicate]

Lesezeit: 5 Minuten

Benutzeravatar von Hesham Eraqi
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.

    – 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 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


Benutzeravatar von kennytm
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:

0.1₁₀ = 0.0001100110011001100110011001100110011001100110011…₂
             ^        ^         ^   ^ 
             1       10        20  24

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

Benutzeravatar von Sven Marnach
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):

>>> "%.55f" % 0.1
'0.1000000000000000055511151231257827021181583404541015625'

Und hier ist der Wert mit einfacher Genauigkeit:

>>> "%.55f" % numpy.float32("0.1")
'0.1000000014901161193847656250000000000000000000000000000'

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.

    – James Kanze

    10. Oktober 2013 um 10:59 Uhr

Benutzeravatar von static_cast
static_cast

Wenn Sie konvertieren .1 zu binär erhalten Sie:

0.000110011001100110011001100110011001100110011001100...

ewig wiederholen

Bei der Zuordnung zu Datentypen erhalten Sie:

float(.1)  = %.00011001100110011001101
                                     ^--- note rounding
double(.1) = %.0001100110011001100110011001100110011001100110011010

Wandeln Sie das in Basis 10 um:

float(.1)  = .10000002384185791015625
double(.1) = .100000000000000088817841970012523233890533447265625

Dies wurde einem Artikel entnommen, der von Bruce Dawson geschrieben wurde. es ist hier zu finden:
Doubles sind keine Floats, also vergleichen Sie sie nicht

  • 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 - Benutzeravatar von Danny Pflughoeft
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;
}

Sehen Warum ist cos(x) != cos(y) wenngleich x == y? Für mehr Information.

Odimegwu Davids Benutzeravatar
Odimegwu David

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;
}

1421070cookie-check0,1 Float ist größer als 0,1 Double. Ich hatte erwartet, dass es falsch ist [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy