Bei der Konvertierung von Integer nach Single kann es zu Genauigkeitsverlusten kommen

27

Ich habe gerade einen Artikel von Microsoft über das Erweitern von Conversions und Option Strict On gelesen, als ich zu dem Teil kam

Die folgenden Konvertierungen können an Genauigkeit verlieren:

  • Ganzzahl bis Single
  • Long zu Single oder Double
  • Dezimal zu einfach oder doppelt

Diese Konvertierungen verlieren jedoch weder Information noch Größe.

.. aber nach einem anderen Artikel in Bezug auf Datentypen ,

  • Integer-Typ kann von -2.147.483.648 bis 2.147.483.647 und speichern

  • Einzelne Art kann von speichern

    • 1,401298E-45 bis 3,4028235E + 38 für positive Zahlen,
    • und -3,4028235E + 38 bis - 1,401298E-45 für negative Zahlen

.. so Single kann viel mehr Zahlen als Integer speichern. Ich konnte nicht verstehen, in welcher Situation eine solche Konvertierung von Integer zu Single an Genauigkeit verlieren könnte. Könnte jemand erklären, bitte?

Vinicius V
quelle

Antworten:

87

Single kann viel mehr Zahlen als Integer speichern

Nein, das kann es nicht. Beide Singleund Integersind 32 Bit, was bedeutet, dass beide genau die gleiche Anzahl von Zahlen speichern können, nämlich 2 32 = 4294967296 verschiedene Zahlen.

Da der Bereich von Singledeutlich größer ist, ist es sofort offensichtlich (aufgrund des Pigeonhole-Prinzips ), dass nicht alle Zahlen innerhalb dieses Bereichs dargestellt werden können.

Und da der Bereich von Integergenau so groß ist wie die maximale Anzahl von Zahlen, die beide Integerund darstellen Singlekönnen, aber Singleauch Zahlen außerhalb dieses Bereichs darstellen können, ist klar, dass er möglicherweise nicht alle Zahlen innerhalb des Bereichs von darstellen kann Integer.

Wenn es einige Zahlen gibt Integer, die nicht in dargestellt werden können Single, muss die Konvertierung von Integernach Single in der Lage sein, Informationen zu verlieren.

Jörg W. Mittag
quelle
3
+1 für diese großartige Erklärung, warum das so sein muss, obwohl die Frage tatsächlich war, wann ("in welcher Situation") es passiert ...
doubleYou
21
@doubleYou: 4261412864 der 4294967296 Integers (99,2%) können nicht als dargestellt Singlewerden. "when" ist also "so ziemlich immer".
Jörg W Mittag
2
Wer genauer sein will, Singlekann nur 4.278.190.079 verschiedene Zahlen darstellen. Ein SingleWert steht nur dann für eine Zahl, wenn der gespeicherte Exponent nicht 255 ist. Dies bedeutet, dass 255 * 2 ^ 24 Singles für Zahlen stehen. Von diesen repräsentieren zwei die gleiche Zahl (nämlich Null), und die anderen repräsentieren alle unterschiedliche Zahlen.
Tanner Swett
10
en.wikipedia.org/wiki/Single-precision_floating-point_format erklärt die Einschränkungen für IEEE754 binary32. Ganzzahlen in [-16777216,16777216](2 ^ 24 = die Breite der Signifikanten) können genau dargestellt werden. Größere Zahlen werden auf das nächste Vielfache von 2, 4, 8, ... gerundet, je nachdem, wie groß sie sind.
Peter Cordes
14
"Was bedeutet, dass beide genau die gleiche Anzahl von Zahlen speichern können" - Das bedeutet nicht , dass. Dies würde nur bedeuten, dass beide Typen genau die gleiche Anzahl von Speichermöglichkeiten für jede Nummer haben. Und das ist nicht der Fall; Zum Beispiel Singlehat zwei Möglichkeiten der Speicherung von Null. So Singlekann in der Tat repräsentiert weniger verschiedene Zahlen als Integer.
Konrad Rudolph
28

Gleitkommatypen (wie Single und Double) werden im Speicher durch ein Vorzeichen, eine Mantisse und einen Exponenten dargestellt. Betrachten Sie es als wissenschaftliche Notation:

Sign*Mantissa*Base^Exponent

Sie verwenden - wie zu erwarten - die Basis 2. Es gibt andere Optimierungen, die die Darstellung von Unendlich und NaN ermöglichen, und der Exponent ist versetzt (wird darauf zurückkommen), und eine Abkürzung für die Mantisse (wird darauf zurückkommen). . Suchen Sie nach dem Standard IEEE 754, der die Darstellung und den Betrieb für weitere Details abdeckt.

Für unsere Zwecke können wir es uns als eine Binärzahl "Mantisse" und einen "Exponenten" vorstellen, der Ihnen sagt, wo Sie das Dezimaltrennzeichen setzen sollen.


Bei Single haben wir 1 Bit für das Vorzeichen, 8 für den Exponenten und 23 für die Mantisse.

Nun ist die Sache, wir werden die Mantisse von der höchstwertigen Stelle speichern. Denken Sie daran, dass alle Nullen links nicht relevant sind. Und da wir binär arbeiten, wissen wir, dass die höchstwertige Ziffer eine 1 ※ ist. Nun, da wir das wissen, müssen wir es nicht speichern. Dank dieser Abkürzung beträgt die effektive Reichweite der Mantisse 24 Bit.

※: Sofern die von uns gespeicherte Nummer nicht Null ist. Dafür werden alle Bits auf Null gesetzt. Wenn wir jedoch versuchen, dies unter der von mir angegebenen Beschreibung zu interpretieren, erhalten Sie eine 2 ^ 24 (die implizite 1) multipliziert mit 1 (2 hoch dem Exponenten 0). Um dies zu beheben, ist Exponent Null ein spezieller Wert. Es gibt auch spezielle Werte, um Unendlich und NaN im Exponenten zu speichern.

Aufgrund des Exponentenoffsets kann - abgesehen von der Vermeidung der Sonderwerte - der Dezimalpunkt vor oder nach dem Beginn der Mantisse gesetzt werden, ohne dass ein Vorzeichen für den Exponenten erforderlich ist.


Dies bedeutet, dass bei großen Zahlen der Gleitkommatyp den Dezimalpunkt hinter das Ende der Mantisse setzt.

Denken Sie daran, dass die Mantisse eine 24-Bit-Zahl ist. Es wird niemals eine 25-Bit-Zahl darstellen ... es hat kein zusätzliches Bit. Daher kann die Single nicht zwischen 2 ^ 24 und 2 ^ 24 + 1 unterscheiden (dies sind die ersten 25 Bit-Zahlen und sie unterscheiden sich beim letzten Bit, das in der Single nicht dargestellt ist).

Für ganze Zahlen beträgt der Bereich der Single also -2 ^ 24 bis 2 ^ 24. Der Versuch, 1 zu 2 ^ 24 zu addieren, führt zu 2 ^ 24 (da 2 ^ 24 und 2 ^ 24 + 1 vom Typ her der gleiche Wert sind). Probieren Sie es online . Aus diesem Grund gehen beim Konvertieren von Integer in Single Informationen verloren. Dies ist auch der Grund, warum eine Schleife, die eine einzelne oder eine doppelte Schleife verwendet, tatsächlich eine Endlosschleife sein kann, ohne dass Sie es merken.

Theraot
quelle
Dies ist keine perfekte Erklärung für das implizite führende 1Bit in der Signifikante. Dies wird dadurch impliziert, dass das vorgespannte Exponentenfeld nicht Null ist . Subnormals (aka denormals) einschließlich+-0.0 eines führenden haben 0etwas von ihrem Signifikanden. Ich denke, Sie könnten es vereinfachen, wenn Sie nur 0.0einen ganz speziellen Fall betrachten, aber 0.0tatsächlich dieselben Kodierungsregeln wie bei anderen Subnormalen befolgen.
Peter Cordes
25

Hier ist ein aktuelles Beispiel dafür, wie beim Konvertieren von Integernach Singledie Genauigkeit verloren gehen kann:

Der SingleTyp kann alle Ganzzahlen von -16777216 bis 16777216 (einschließlich) speichern, aber nicht alle Ganzzahlen außerhalb dieses Bereichs. Beispielsweise kann die Nummer 16777217 nicht gespeichert werden. Außerdem kann keine ungerade Nummer gespeichert werden, die größer als 16777216 ist.

Wir können Windows PowerShell verwenden, um zu sehen, was passiert, wenn wir ein Integerin ein Singleund zurück konvertieren :

PS C:\Users\tanne> [int][float]16777213
16777213
PS C:\Users\tanne> [int][float]16777214
16777214
PS C:\Users\tanne> [int][float]16777215
16777215
PS C:\Users\tanne> [int][float]16777216
16777216
PS C:\Users\tanne> [int][float]16777217
16777216
PS C:\Users\tanne> [int][float]16777218
16777218
PS C:\Users\tanne> [int][float]16777219
16777220

Beachten Sie, dass 16777217 auf 16777216 und 16777219 auf 16777220 abgerundet wurden.

Tanner Swett
quelle
4
Und mit zunehmender Größe floatwächst der Abstand zwischen den nächsten darstellbaren s als Potenzen von. en.wikipedia.org/wiki/…
Peter Cordes
12

Gleitkommatypen ähneln der "wissenschaftlichen Notation" in der Physik. Die Zahl wird in ein Vorzeichenbit, einen Exponenten (Multiplikator) und eine Mantisse (signifikante Ziffern) aufgeteilt. Mit zunehmender Größe des Werts nimmt auch die Schrittgröße zu.

Gleitkommazahlen mit einfacher Genauigkeit haben 23 Mantissenbits, aber es gibt eine "implizite 1", so dass die Mantisse effektiv 24 Bits beträgt. Daher können alle Ganzzahlen mit einer Größe von bis zu 2 24 genau in Gleitkommazahlen mit einfacher Genauigkeit dargestellt werden.

Darüber können sukzessive weniger Zahlen dargestellt werden.

  • Von 2 24 bis 2 25 können nur gerade Zahlen dargestellt werden.
  • Von 2 25 bis 2 26 können nur Vielfache von 4 dargestellt werden.
  • Von 2 26 bis 2 27 können nur Vielfache von 8 dargestellt werden.
  • Von 2 27 bis 2 28 können nur Vielfache von 16 dargestellt werden
  • Von 2 28 bis 2 29 können nur Vielfache von 32 dargestellt werden
  • Von 2 29 bis 2 30 können nur Vielfache von 64 dargestellt werden
  • Von 2 30 bis 2 31 können nur Vielfache von 128 dargestellt werden

Von den 2 32 möglichen 32-Bit-Ganzzahlen mit Vorzeichen können also nur 2 * (2 24 + 7 * 2 23 ) = 9 * 2 24 in Gleitkommazahlen mit einfacher Genauigkeit dargestellt werden. Das sind 3.515625% der Gesamtsumme.

Peter Green
quelle
8

Schwimmer mit einfacher Genauigkeit haben eine Genauigkeit von 24 Bit. Alles darüber hinaus wird auf die nächste 24-Bit-Zahl gerundet. In der wissenschaftlichen Dezimalschreibweise ist es vielleicht einfacher zu verstehen, aber beachten Sie, dass die tatsächlichen Floats Binärwerte verwenden.

Angenommen, Sie haben 5 Dezimalstellen des Speichers. Sie können diese wie ein reguläres vorzeichenloses int verwenden, sodass Sie eine beliebige Zahl zwischen 0 und 99999 haben können. Wenn Sie größere Zahlen darstellen möchten, können Sie die wissenschaftliche Notation verwenden und nur zwei Ziffern als Exponenten zuweisen Sie können jetzt alles zwischen 0 und 9,99 x 10 99 darstellen .

Die größte Zahl, die Sie genau darstellen können, ist jetzt jedoch nur 999. Wenn Sie versuchen, 12345 darzustellen, können Sie 1,23 x 10 4 oder 1,24 x 10 4 erhalten , aber Sie können keine der dazwischen liegenden Zahlen darstellen, weil Sie Es sind nicht genügend Ziffern verfügbar.

Karl Bielefeldt
quelle
3
Die Verwendung von Dezimalstellen ist eine nette Idee, die das Verständnis erleichtert, aber der letzte Absatz ist etwas irreführend : Tatsächlich können Sie Zahlen über 999 darstellen, und Ihr Beispiel zeigt dies: 12300 wäre 1,23 x 10 <sup> 4 <sup >. Sie meinen, dass es ab dieser Zahl Lücken gibt. Würde es Ihnen etwas ausmachen, es ein wenig umzuformulieren?
Fabio sagt Reinstate Monica