float-vergleich



  • hi

    garantiert der standard, dass der ==-operator bei zwei floats bitweise überprüft? ich will, dass meine beiden floats bitweise verglichen werden, bin mir aber nicht sicher, ob ich es erst in ein char-array splitten muss oder ob es direkt geht.



  • Nein, ist es afaik nicht - es wird ja noch nicht einmal vom Standard festgelegt, wie ein float aufgebaut ist.


  • Mod

    Nein, davon kannst du nicht ausgehen. Du darfst sogar im Gegenteil davon ausgehen, dass dies nicht so passiert. Es ist zwar im Standard nicht genau festgelegt, was passiert, aber wenn der float einem der gängigen Fließkommastandards entspricht, ist dies definitiv nicht der Fall (und das aus gutem Grund!).

    bist du wirklich sicher, dass du eine bitweise Gleichheit möchtest? Darf ich fragen, warum?



  • ich will checken ob ein float NAN ist. und um NAN zu sein, muss der float doch exakt gleich wie quiet_nan() oder signaling_nan() aus numeric_limits sein.


  • Mod

    lol_of_lolcraft schrieb:

    ich will checken ob ein float NAN ist. und um NAN zu sein, muss der float doch exakt gleich wie quiet_nan() oder signaling_nan() aus numeric_limits sein.

    Ahh, also genau der Fall, wo trotz bitweiser Gleichheit false heraus kommt. Falls dein Compiler C99 kann, dann gibt's in der cmath (bzw. math.h) eine Funktion isnan. Falls nicht, gibt es das auch von boost:
    http://www.boost.org/doc/libs/1_41_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/fpclass.html

    Oder wenn es sein muss auch von Hand:

    bool isnan(double d)
    {
      return d != d;
    }
    

    Diese Funktionen sollten auch mit exotischen NaNs zurechtkommen. Es ist schließlich nicht festgeschrieben, dass es nur eine Bitrepräsentierung dafür gibt.



  • x!=x   <=>   x ist NaN
    

    Das ist zumindest bei IEEE-754 Floatingpointarithmetik der Fall. Es gibt aber hier und da auch Compilererweiterungen à la isnan(x). Der kommende C++ Standard wird auch so eine Funktion über <cmath> zur Verfügung stellen.

    Edit: Mist! Zu spät. 🙂



  • lol_of_lolcraft schrieb:

    ich will checken ob ein float NAN ist. und um NAN zu sein, muss der float doch exakt gleich wie quiet_nan() oder signaling_nan() aus numeric_limits sein.

    Mal frech von boost geklaut:

    If all exponent bits are 1 and at least one significand bit is 1, then the number is a not-a-number.

    D. h. in IEEE 754 gibt es unterschiedliche NaNs. Also wird dein bitweiser Vergleich nix.



  • SeppJ schrieb:

    Oder wenn es sein muss auch von Hand:

    bool isnan(double d)
    {
      return d != d;
    }
    

    Ist es eigentlich garantiert (-> Portabilität), dass dabei nicht irgendwelche Floating-Point-Exceptions fliegen?

    /edit:
    Und warum geben isnan von C++0x und Konsorten int und nicht bool zurück? Hat das einen tieferen Sinn?


  • Mod

    berndbernd schrieb:

    Ist es eigentlich garantiert (-> Portabilität), dass dabei nicht irgendwelche Floating-Point-Exceptions fliegen?

    Mir wäre nicht bekannt, dass ein NaN-Vergleich eine FP-Exception ist. Vielmehr wäre die Operation die das NaN verursacht hat ein Fall dafür.

    /edit:
    Und warum geben isnan von C++0x und Konsorten int und nicht bool zurück? Hat das einen tieferen Sinn?

    Vermutlich weil die C-Variante einen int zurückgibt und man Funktionen nicht anhand des Rückgabewertes überladen kann. Und die C-Variante gibt int zurück, weil selbst der C99-Bool nur eine Krücke die intern meistens ein int ist.



  • SeppJ schrieb:

    /edit:
    Und warum geben isnan von C++0x und Konsorten int und nicht bool zurück? Hat das einen tieferen Sinn?

    Vermutlich weil die C-Variante einen int zurückgibt und man Funktionen nicht anhand des Rückgabewertes überladen kann. Und die C-Variante gibt int zurück, weil selbst der C99-Bool nur eine Krücke die intern meistens ein int ist.

    Jo, das hatte ich schon vermutet. Alte Zöpfe ... 🙂


  • Mod

    berndbernd schrieb:

    Jo, das hatte ich schon vermutet. Alte Zöpfe ... 🙂

    Ich wette intern sind die C++-Bools bestimmt auch meistens ints (Außer das verstoßene Kind vector<bool> 😉 ), man merkt es bloß nicht so stark.



  • Also unter VS2010 ist jedenfalls sizeof(bool) == 1 und nicht vier. Oder meinst du auf CPU-Ebene?


  • Mod

    berndbernd schrieb:

    Also unter VS2010 ist jedenfalls sizeof(bool) == 1 und nicht vier. Oder meinst du auf CPU-Ebene?

    Nein, dann habe ich mich wohl geirrt und im Hintergrund mehr C-Kompatibilität vermutet als eigentlich da ist.



  • Wieso haben die netten Leute die den C99-Standard ausgearbeitet haben nicht char als bool genommen? Ist doch blödsinnig, einfach so Speicher zu verschenken...


  • Mod

    EOutOfResources schrieb:

    Wieso haben die netten Leute die den C99-Standard ausgearbeitet haben nicht char als bool genommen? Ist doch blödsinnig, einfach so Speicher zu verschenken...

    Strenggenommen haben sie _Bool als bool definiert 😃 . Was das intern ist, bleibt den Compilerherstellern überlassen. Aber boolsche Werte werden in C traditionell per int übergeben. Normalerweise leben solche übergebenen Werte dann nicht lange.



  • Der benötigte Speicherplatz ist vor allem dann relevant, wenn man viele Wahrheitswerte aufs Mal benötigt (z.B. in einem Array). In diesem Fall hätten die C-Programmierer wahrscheinlich weniger Hemmungen, direkt bitweise zu arbeiten. Das ist dann immer noch 8 Mal speichereffizienter als bool , hat aber auch seine Schattenseiten.



  • EOutOfResources schrieb:

    Wieso haben die netten Leute die den C99-Standard ausgearbeitet haben nicht char als bool genommen? Ist doch blödsinnig, einfach so Speicher zu verschenken...

    CPU-Zeit ist teurer als Speicher und 32bit Operationen werden auf heutigen x86(_64) CPUs deutlich schneller ausgeführt als 8bit.



  • Ethon schrieb:

    EOutOfResources schrieb:

    Wieso haben die netten Leute die den C99-Standard ausgearbeitet haben nicht char als bool genommen? Ist doch blödsinnig, einfach so Speicher zu verschenken...

    CPU-Zeit ist teurer als Speicher und 32bit Operationen werden auf heutigen x86(_64) CPUs deutlich schneller ausgeführt als 8bit.

    D.h. C89 ist schneller als C++ und C99, weil int üblicherweise 4, bool und _Bool aber nur 1 Byte hat?

    Bedenke dass der Compiler immer noch selbst optimieren kann (z.B. im Bezug auf Padding, verwendete Assemblerbefehler und Register). In C89 hat sich wahrscheinlich einfach int durchgesetzt, weil es nichts Besseres gab und int halt der Standard-Datentyp darstellte.



  • Ethon schrieb:

    CPU-Zeit ist teurer als Speicher und 32bit Operationen werden auf heutigen x86(_64) CPUs deutlich schneller ausgeführt als 8bit.

    Das glaube ich so nicht.



  • CPU-Zeit ist teurer als Speicher [...]

    Das konnte man vielleicht vor 10 Jahren so sagen. Inzwischen geht das nicht mehr so einfach. Die CPU is durchaus schonmal am idlen, weil sie auf Daten ausm Speicher warten muss. Wenn die Datentypen größer werden, passt weniger in den cache, und wenn der prefetcher das Zeug dann auch nicht rechtzeitig ausm RAM holt/holen kann...


Log in to reply