Genauigkeit der Multiplikation mit 1,0 und Umwandlung von Int in Float

Lesezeit: 4 Minuten

Benutzeravatar von Violet Giraffe
Violette Giraffe

Kann man davon ausgehen, dass die Bedingung (int)(i * 1.0f) == i gilt für jede ganze Zahl i?

  • Ich nehme an, dass es so ist, weil alle Mantissenbits verloren gehen. Ich weiß nicht, ob int wird befördert float jedoch.

    – Toni der Löwe

    15. November 2012 um 15:32 Uhr


  • Aus irgendeinem Grund möchte ich sagen neinaber ich habe wirklich keine Rechtfertigung dafür… :-]

    Benutzer131441

    15. November 2012 um 15:32 Uhr


  • @John: Ich habe das gleiche Gefühl. Ich habe auch über große ganze Zahlen nachgedacht und ob es eine Garantie für die Multiplikation mit gibt 1.0… wahrscheinlich ist die Antwort in IEEE754 “ja”.

    – Kerrek SB

    15. November 2012 um 15:33 Uhr

  • @John: Das war auch mein anfängliches Gefühl, jetzt weiß ich es einfach nicht 🙂

    – Violette Giraffe

    15. November 2012 um 15:34 Uhr

Benutzeravatar von Stephen Canon
Stefan Kanon

Nein.

Wenn i ausreichend groß ist, dass int(float(i)) != i (unter der Annahme, dass Float IEEE-754 mit einfacher Genauigkeit ist, i = 0x1000001 genügt, dies zu zeigen), dann ist dies falsch, weil Multiplikation mit 1.0f erzwingt eine Umstellung auf floatdie den Wert ändert, obwohl die nachfolgende Multiplikation dies nicht tut.

jedoch, wenn i ist eine 32-Bit-Ganzzahl und double ist IEEE-754 doppelt, dann ist es ist stimmt das int(i*1.0) == i.


Nur um ganz klar zu sein, Multiplikation mit 1.0f ist genau. Es ist die Konvertierung von int zu float das kann nicht sein.

  • Um diese Antwort zu ergänzen: Einfach ausgedrückt ist der Genauigkeitsverlust darauf zurückzuführen, dass Float nur 24 Bits hat, um das Int aufzunehmen, während ein Int 32 Bits hat und daher die niederwertigsten Bits während der Umwandlung gerundet werden.

    – Ifthikhan

    15. November 2012 um 15:52 Uhr


  • gerundetnicht verworfenaber ja, genau.

    – Stefan Kanon

    15. November 2012 um 15:53 ​​Uhr


  • @anatolyg: Nein. In C++ wird dies durch Absatz 10 von Abschnitt 5 (the übliche arithmetische Umrechnungen): “Wenn einer der Operanden Float ist, soll der andere in Float konvertiert werden.” So i umgewandelt wird float vor der Multiplikation, die eine Rundung bewirkt.

    – Stefan Kanon

    15. November 2012 um 15:59 Uhr


  • @MichaelShopsin: Genau einer von a <= b oder a > b ist wahr, es sei denn a oder b ist ein NaN.

    – Eric Postpischil

    16. November 2012 um 2:22 Uhr

  • @MichaelShopsin: Ihr habt beide Recht. Erics Aussage trifft absolut auf Fließkommazahlen zu, wie sie vom Standard definiert werden. Es gab jedoch gut dokumentierte Compilerfehler, die das von Michael beschriebene Verhalten hervorriefen. Um es jedoch klarzustellen, dies ist kein Problem von Fließkommavergleichen; es ist ein Problem fehlerhafter Compiler.

    – Stefan Kanon

    16. November 2012 um 18:28 Uhr


Benutzeravatar von thkala
thkala

Nein, IEEE-754 Fließkommazahlen haben einen größeren dynamischen Bereich als ganze Zahlen auf Kosten der ganzzahligen Genauigkeit bei gleicher Bitbreite.

Siehe zum Beispiel die Ausgabe dieses kleinen Snippets:

int main() {
        int x = 43046721;

        float y = x;

        printf("%d\n", x);
        printf("%f\n", y);
}

43046721 kann in den 24 Bits an Genauigkeit, die in einem 32-Bit-Format verfügbar sind, nicht korrekt dargestellt werden float Nummer, also ist die Ausgabe etwas in dieser Richtung:

43046721
43046720.000000

Tatsächlich würde ich erwarten, dass jede ungerade Zahl über 16.777.216 das gleiche Problem hat, wenn sie in eine 32-Bit-Version konvertiert wird float Nummer.

Ein paar interessante Punkte:

  • Das hat mehr mit der impliziten Konvertierung von int nach Float zu tun als mit der Multiplikation selbst.

  • Dies ist keineswegs einzigartig für C – zum Beispiel unterliegt Java genau demselben Problem.

  • Die meisten Compiler haben Optimierungsoptionen, die sich darauf auswirken können, wie solche Konvertierungen gehandhabt werden, indem bestimmte Einschränkungen des Standards ignoriert werden. In einem solchen Fall, (int)((float)x * 1.0f) == x könnte immer sein true wenn der Compiler die Konvertierung optimiert float und zurück.

Ciro Santilli Benutzeravatar von OurBigBook.com
Ciro Santilli OurBigBook.com

Nein, das Verhalten ist implementierungsdefiniert, da C und C++ IEEE-754 nicht benötigen, obwohl dies bei weitem die gebräuchlichste Darstellung ist.

So stellen Sie sicher, dass IEEE-754 verwendet wird:

  • in C verwenden #ifdef __STDC_IEC_559__
  • Verwenden Sie in C++ die std::numeric_limits<float>::is_iec559 Konstanten

  • Gut zu wissen, danke! Kennen Sie moderne (oder derzeit verwendete) Implementierungen, die NICHT IEEE-754-konform sind?

    – Violette Giraffe

    15. Juni 2015 um 15:32 Uhr


Benutzeravatar von Mohit Sehgal
Mohit Sehgal

Nein, es ist wegen der Typumwandlung für alle ganzen Zahlen absolut falsch. Code überprüfen.

#include <stdio.h>

int main()
{
    int i = 0;
    for (; i < 2147483647; ++i) {
        if ((int)(i * 1.0f) != i) {
            printf("not equal\n");
            break;
        }
    }
    printf("out of the loop\n");
    getchar();
    return 0;
}

Dieser Code geht davon aus, dass Sie eine 32-Bit-Ganzzahl verwenden

1405590cookie-checkGenauigkeit der Multiplikation mit 1,0 und Umwandlung von Int in Float

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

Privacy policy