2010-10-08 18 views
5

Mögliche Duplizieren dargestellt werden kann:
Which is the first integer that an IEEE 754 float is incapable of representing exactly?Finding die kleinste ganze Zahl, die nicht als IEEE-754 32-Bit-Float

Zum einen ist sie eine Hausaufgaben Frage, um nur diese löschen sofort auf. Ich bin natürlich nicht auf der Suche nach einem Löffel, nur ein kleiner Hinweis auf die richtige Richtung.

Meine Aufgabe besteht also darin, die kleinste positive ganze Zahl zu finden, die nicht als IEEE-754-Float (32 Bit) dargestellt werden kann. Ich weiß, dass das Testen für die Gleichstellung auf so etwas wie „5 == 5,00000000001“ wird fehlschlagen, so dass ich dachte, ich würde einfach Schleife über alle Zahlen und Test für die in dieser Art und Weise:

int main(int argc, char **argv) 
{ 
    unsigned int i; /* Loop counter. No need to inizialize here. */ 

    /* Header output */ 
    printf("IEEE floating point rounding failure detection\n\n"); 

    /* Main program processing */ 
    /* Loop over every integer number */ 
    for (i = 0;; ++i) 
    { 
     float result = (float)i; 

     /* TODO: Break condition for integer wrapping */ 

     /* Test integer representation against the IEEE-754 representation */ 
     if (result != i) 
      break; /* Break the loop here */ 
    } 

    /* Result output */ 
    printf("The smallest integer that can not be precisely represented as IEEE-754" 
      " is:\n\t%d", i); 


    return 0; 
} 

Dies schlug fehl. Dann habe ich versucht, die Ganzzahl "i" von dem Fließkomma "Ergebnis" zu subtrahieren, das "i" ist, in der Hoffnung, etwas von "0.000000002" zu erreichen, das ich versuchen könnte, zu erkennen, was ebenfalls fehlgeschlagen ist.

Kann mir jemand eine Eigenschaft von Gleitkommazahlen zeigen, auf die ich mich verlassen kann, um die gewünschte Bruchbedingung zu erhalten?

-------------------- aktualisieren unten ---------------

Vielen Dank für Hilfe zu diesem Thema ein! Ich lernte hier mehrere Dinge:

  1. Mein ursprünglicher Gedanke war in der Tat richtig und bestimmt das Ergebnis auf der Maschine beabsichtigt wurde, auf (Solaris 10, 32 Bit) ausgeführt werden sollte, doch scheiterte auf meinen Linux-Systemen zu arbeiten (64 Bit und 32 Bit).

  2. Die Änderungen, die Hans Passant das Programm auch mit meinen Systemen arbeiten, gibt gemacht hinzugefügt scheinen einige Unterschiede zwischen den Plattformen geht hier zu sein, dass ich nicht erwartet hatte,

Vielen Dank an alle!

+0

Wie schlägt es fehl? Wenn ich deinen Code kompiliere und ausführe, ist die Ausgabe 16777217. – Henrik

+0

@KennyTM: Verdammt, und ich dachte, dass ich gut im Suchen war! Entschuldigung für das Duplizieren dann. – LukeN

+0

@Henrik: Es wickelte nur zurück (INT_MAX -> 0) und brach nie mit einem Ergebnis. – LukeN

Antwort

5

Das Problem ist, dass Ihr Gleichheitstest ein Fließkomma-Test ist.Die i Variable wird zuerst in float umgewandelt und das erzeugt natürlich den gleichen float. Konvertiere den Gleitkommawert zurück in int, um einen ganzzahligen Gleichheitstest zu erhalten:

float result = (float)i; 
int truncated = (int)result; 
if (truncated != i) break; 

Wenn es mit den Ziffern 16 beginnt, dann hast du den richtigen gefunden. Wandle es in ein Sechseck um und erkläre, warum das das war, was für einen Notenbonus fehlgeschlagen ist.

+0

Danke! Das hat den Trick gemacht und ich bin froh, dass meine ursprüngliche Idee bewiesen hat, dass sie gültig ist :) – LukeN

2

Ich glaube, Sie auf die Darstellung der Gleitkommazahlen als (Basis, Zeichen, Signifikanden, Exponent) Grund sollte

Hier ist ein Auszug aus Wikipedia, dass Sie einen Hinweis geben kann:

Ein gegebenes Format umfasst:

* Finite numbers, which may be either base 2 (binary) or base 10 

(dezimal). Jede endliche Zahl ist am einfachsten einfach durch drei ganze Zahlen beschrieben: s = ein Vorzeichen (Null oder Eins), c = eine Signifikanz (oder 'Koeffizient'), q = ein Exponent. Der numerische Wert einer endlichen Zahl ist (-1) s × c × bq wobei b die Base (2 oder 10) ist. Wenn zum Beispiel das Vorzeichen 1 (negativ) ist, der Signifikanzwert 12345 ist, der Exponent -3 ist und die Basis 10 ist, dann ist der Wert der Nummer -12.345.

0

Das wäre FLT_MAX+1. Siehe float.h.

Edit: oder eigentlich nicht. Überprüfen Sie die modf() Funktion in math.h

+0

Nein. Hast du es versucht? –

+0

@Hans Ja, es gibt definitiv kleinere Zahlen, die nicht dargestellt werden können. –

+1

Versuchen Sie stattdessen '(1 << FLT_MANT_DIG) + 1'. –

Verwandte Themen