2010-04-17 9 views
9

Ich bin eine gutartige Warnung über einen möglichen Datenverlust immerWarnung vor Datenverlust C++/C

C4244 Warnung: ‚Argument‘: Konvertierung von ‚const int‘ zu ‚schweben‘, einen möglichen Datenverlust

Frage

ich erinnere mich, als ob Schwimmer eine größere Genauigkeit als int hat. Wie können also Daten verloren gehen, wenn ich von einem kleineren Datentyp (int) in einen größeren Datentyp (float) umwandle?

+0

Nichts mit Ihrem spezifischen Problem zu tun, aber wenn Sie glauben, dass floats irgendwie schneller als verdoppelt sein können, liegen Sie falsch - der Zweck von floats ist es, Speicheranforderungen zu minimieren, die für moderne Anwendungen selten ein Problem sind. Ihre Standardauswahl für den Datentyp sollte Double, nicht Float sein. –

+1

@Neil: Das hängt sehr von der CPU ab. Es gibt viele Architekturen, bei denen Float dramatisch schneller ist als doppelt. – jalf

+0

@jalf Möglich, aber in den meisten Situationen in C- oder C++ - Code werden die Floats trotzdem zu Doubles hochgestuft. –

Antwort

14

Weil float Zahlen nicht genau sind. Sie können nicht jeden möglichen Wert darstellen, den ein int in einem float halten kann, obwohl der Höchstwert eines float viel höher ist.

So führen Sie dieses einfache Programm:

#include <stdio.h> 

int main() 
{ 
for(int i = 0; i < 2147483647; i++) 
{ 
    float value = i; 
    int ivalue = value; 
    if(i != ivalue) 
    printf("Integer %d is represented as %d in a float\n", i, ivalue); 
} 
} 

Sie schnell sehen werden, dass es Tausende Milliarden von ganzen Zahlen, die nicht als float s dargestellt werden kann. Zum Beispiel sind alle ganzen Zahlen zwischen dem Bereich 16,777,219 und 16,777,221 als 16,777,220 dargestellt.

EDIT wieder das Programm über Laufen zeigt, dass es 2.071.986.175positive ganze Zahlen sind, die nicht gerade als float s dargestellt werden kann. Das lässt Sie grob mit nur 100 Millionen positiven Integer, die richtig in eine float passen. Dies bedeutet, dass nur eine ganze Zahl von richtig ist, wenn Sie es in einen Schwimmer setzen.

Ich erwarte, dass die Zahlen für die negativen ganzen Zahlen gleich sind.

+0

@BlueNovember: Jede ganze Zahl> 2^24. – Stephen

+0

Nicht Tausende. Milliarden. – slacker

+0

Ihr Code konvertiert einen Float (größer) in int (kleiner), also unterstütze ich möglicherweise Datenverlust. Meine Frage ist über int zu floaten –

6

Auf den meisten Architekturen int und float sind die gleiche Größe, in der sie die gleiche Anzahl von Bits haben. In einem Gleitkomma werden diese Bits jedoch zwischen Exponent und Mantisse aufgeteilt, was bedeutet, dass es im Float tatsächlich weniger Bits Genauigkeit gibt als Int. Dies ist jedoch wahrscheinlich nur ein Problem für größere Ganzzahlen.

Auf Systemen, in denen ein int 32 Bits ist, ist ein double normalerweise 64 Bits und kann so genau jeden Int.

3

Beide Typen bestehen aus 4 Bytes (32 Bits). Nur einer von ihnen erlaubt einen Bruchteil (den Float).

Nehmen Sie dies für ein Float-Beispiel;

34,156

(integer) (Fraktion)

Jetzt ist Ihre Logik verwenden. Wenn einer von ihnen muss Fraktionsinformationen speichern (schließlich sollte es eine Zahl darstellen), dann bedeutet es, dass es weniger Bits für den ganzzahligen Teil hat.

So kann ein float eine maximale ganze Zahl darstellen, die kleiner als die Int-Typ-Fähigkeit ist.

Um genauer zu sein, verwendet ein "int" 32 Bits, um eine ganze Zahl darzustellen (maximal vorzeichenlose ganze Zahl von 4.294.967.296). Ein "float" verwendet dazu 23 Bits (maximal vorzeichenlose ganze Zahl von 8.388.608).

Deshalb, wenn Sie von Int in Float konvertieren, können Sie Daten verlieren.

Beispiel: int = 1.158.354.125

Sie können nicht speichern Sie diese Nummer in einem "schweben".

Weitere Informationen unter:

http://en.wikipedia.org/wiki/Single_precision_floating-point_format

http://en.wikipedia.org/wiki/Integer_%28computer_science%29

+0

Das ist aus ein paar Gründen etwas falsch. Einer von ihnen ist der "Float" mit 24 Bits für die Mantisse, nicht 23. Also ist jede vorzeichenlose ganze Zahl bis 16777216 genau darstellbar. – slacker

+0

Wie viele Bits werden für die Mantisa doppelt verwendet? –

+0

Der IEEE 754-Einzelschwimmer hat 23 Mantissenbits, was einen effektiven Bereich von 24 Bits ergibt, weil der Exponent normalisiert ist. Die Mantisse "stiehlt" ein bisschen vom Exponenten. –

0

A float sind in der Regel in dem Standard IEEE Format mit einfacher Genauigkeit. Dies bedeutet, dass es in einem float nur 24 Bits Genauigkeit gibt, während ein int wahrscheinlich 32-Bit ist. Wenn also Ihre int eine Zahl enthält, deren absoluter Wert nicht in 24 Bit passen kann, wird sie wahrscheinlich auf die nächste darstellbare Zahl gerundet.

+0

Nit: "Präzision" hat eine Standardbedeutung, die nur zufällig auf den Bereich der darstellbaren Zahlen bezogen ist. "Präzision" ist die kleinste positive Zahl, die zu 1.0 addiert werden kann und eine Zahl ergibt, die sich von 1.0 unterscheidet. Die Genauigkeit eines Int ist also 1 (ein Bit, nicht 31 oder 32). Die Genauigkeit eines IEEE 754-Einzelschwimmers beträgt ungefähr 5.96e-8 (24 Bit). –

+0

@Jive Dadson: Ich verwendete das Wort "Präzision" auf eine eher lockere (non-formale) Weise. In dieser Antwort bedeutet es offensichtlich "Anzahl der signifikanten Bits". – slacker

1

Präzision spielt keine Rolle. Die Genauigkeit von int ist 1, während die Genauigkeit eines typischen Floats (IEEE 754 single precision) ungefähr 5.96e-8 beträgt. Was zählt, sind die Mengen von Zahlen, die die zwei Formate darstellen können. Wenn es Zahlen gibt, die int genau das Float darstellen kann, dann besteht ein möglicher Datenverlust.

Floats und Ints sind in der Regel beide 32 Bits in diesen Tagen, aber das ist nicht garantiert. Angenommen, dies ist auf Ihrer Maschine der Fall, folgt daraus, dass es int-Werte geben muss, die float nicht genau darstellen kann, da es offensichtlich Gleitkommawerte gibt, die int nicht genau darstellen kann. Der Bereich eines Formats kann kein richtiger Super-Satz des anderen sein, wenn beide Formate die gleiche Anzahl von Bits effizient verwenden.

Ein 32-Bit-Int hat effektiv 31 Bits, die für den absoluten Wert der Zahl codieren. Ein IEEE-754-Float hat effektiv nur 24 Bits, die für die Mantisse kodieren (eine implizite).

0

Fakt ist, dass sowohl ein float als auch ein int mit 32 Bits dargestellt werden. Der ganzzahlige Wert verwendet alle 32 Bits, so dass er Zahlen von -2 -1 aufnehmen kann. Ein Float verwendet jedoch 1 Bit für das Vorzeichen (einschließlich -0,0f) und 8 Bit für den Exponenten. Die Mittel 32 - 9 = 23 Bits übrig für die Mantisse. Der Float setzt jedoch voraus, dass, wenn die Mantisse und der Exponent nicht Null sind, die Mantisse mit einer 1 beginnt. Sie haben also mehr oder weniger 24 Bit für Ihre ganze Zahl anstelle von 32. Da sie jedoch verschoben werden kann, bringt sie mehr als 2 ganze Zahlen.

A floating point uses a Sign, an eXponent, and a Mantissa 
S X X X X X X X X M M M M M M M M M M M M M M M M M M M M M M M 

An integer has a Sign, and a Mantissa 
S M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M 

also eine ganze Zahl wie:

1 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 

in einem Schwimmer passt, weil es verschoben werden kann:

1 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 
|  |        | 
|  +---------+     +---------+ 
|     |        | 
v     v        v 
S X X X X X X X X M M M M M M M M M M M M M M M M M M M M M M M 
1     1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 

ich dich nicht der Exponent zeigen, weil ich am häufigsten Machen Sie einen Fehler bei der Berechnung, aber es sollte etwa 5 (oder -5?) sein, weil ich um 5 Bits verschoben habe (aber Sie müssen 128 addieren oder subtrahieren ...). Dies zeigt deutlich, dass wenn Sie um 5 Bits verschieben müssen, Sie die 5 unteren Bits verlieren.

So kann diese andere Ganzzahl in einen Float mit einem Verlust von 2 Bits umgewandelt werden (dh wenn Sie wieder in eine ganze Zahl konvertieren, werden die letzten zwei Bits (11) auf Null gesetzt, da sie nicht gespeichert wurden) der Schwimmer):

1 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 
|  |        |    | | | | | 
|  +---------+     +---------+  +-+-+-+-+--> all lost 
|     |        | 
v     v        v 
S X X X X X X X X M M M M M M M M M M M M M M M M M M M M M M M 
1     1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 

Ziemlich einfache Sachen wirklich.

WICHTIGER HINWEIS: Ja, die erste 1 in der ganzen Zahl ist das Vorzeichen, dann die nächste 1 wird nicht in die Mantisse kopiert, es wird angenommen, dass sie 1 ist, also ist es nicht erforderlich.

Verwandte Themen