Der Wert von „const float“ unterscheidet sich von „float“, wenn er in C# in „int“ umgewandelt wird.

StackOverflow https://stackoverflow.com//questions/24016294

  •  21-12-2019
  •  | 
  •  

Frage

Kann jemand von euch erklären, warum das passiert?

static void Main()
{
    const float xScaleStart = 0.5f;
    const float xScaleStop = 4.0f;
    const float xScaleInterval = 0.1f;
    const float xScaleAmplitude = xScaleStop - xScaleStart;

    const float xScaleSizeC = xScaleAmplitude / xScaleInterval;

    float xScaleSize = xScaleAmplitude / xScaleInterval;

    Console.WriteLine(">const float {0}, (int){1}", xScaleSizeC, (int)xScaleSizeC);

    Console.WriteLine(">      float {0}, (int){1}", xScaleSize, (int)xScaleSize);

    Console.ReadLine();
}

Ausgabe:

>const float 35, (int)34
>      float 35, (int)35

Ich weiß, dass die binäre Darstellung von 0,1 tatsächlich 0,09999990463256835937 ist, aber warum passiert das bei Verwendung von „const float“ und nicht bei „float“?Wird dies als Compilerfehler angesehen?

Fürs Protokoll: Der Code wird wie folgt kompiliert:

private static void Main(string[] args)
{
    float xScaleSize = 35f;
    Console.WriteLine(">const float {0}, (int){1}", 35f, 34);
    Console.WriteLine(">      float {0}, (int){1}", xScaleSize, (int)xScaleSize);
    Console.ReadLine();
}
War es hilfreich?

Lösung

Das „Warum“ davon läuft im Wesentlichen auf die Tatsache hinaus, dass es bei der Arbeit häufig so ist float Für Daten kann eine interne Darstellung verwendet werden, die präziser ist als angegeben float oder double.Dies wird ausdrücklich in der Spezifikation des Virtual Execution System (VES) (Abschnitt 12 von Teilung I):

Die Schwimmpunktzahlen werden unter Verwendung eines internen Gleitkomma-Typs dargestellt.In jedem dieser Fälle ist der nominale Typ der Variablen oder des Ausdrucks entweder float32 oder float64, aber sein Wert kann intern mit zusätzlichem Bereich und/oder Präzision vertreten werden

Und später haben wir:

Die Verwendung einer internen Darstellung, die breiter ist als float32 oder float64 Kann Unterschiede in den Berechnungsergebnissen verursachen, wenn ein Entwickler scheinbar unabhängige Modifikationen zu seinem Code vornimmt. Das Ergebnis kann sein, dass ein Wert aus der internen Darstellung (z. B. in einem Register) zu einem Ort auf dem Stapel verschüttet wird.

Nun, laut der C#-Sprachspezifikation:

Die Auswertung konstanter Ausdrücke zur Kompilierungszeit verwendet dieselben Regeln wie die Auswertung nicht konstanter Ausdrücke zur Laufzeit, mit der Ausnahme, dass dort, wo die Auswertung zur Laufzeit eine Ausnahme ausgelöst hätte, bei der Auswertung zur Kompilierungszeit ein Kompilierungszeitfehler auftritt.

Aber wie wir oben beobachten, erlauben die Regeln tatsächlich zeitweise die Verwendung höherer Präzision, und wann diese erhöhte Präzision verwendet wird, unterliegt nicht unserer direkten Kontrolle.


Und natürlich hätten die Ergebnisse unter anderen Umständen genau das Gegenteil von dem sein können, was Sie beobachtet haben – der Compiler wäre möglicherweise auf eine niedrigere Präzision zurückgefallen und die Laufzeit hätte stattdessen eine höhere Präzision beibehalten können.

Andere Tipps

Ich kann nicht sagen, dass dies eine doppelte Frage ist, seit hier -> Eric Postpischil Kommentar

erklärte etwas Ähnliches in Bezug auf Int's und Const Int.

Die Hauptidee ist, dass die Abteilung von zwei Konstanten, die vom Compiler berechnet werden, bevor der Code generiert wird, und nicht in der Laufzeit, jedoch in diesem speziellen Fall, wenn der Compiler dies tat, wenn der Compiler diese Berechnungen in doppelt leistet> Format.So ist der XSCALESEC grundsätzlich gleich 34.9999 ... also, wenn es in der Laufzeit von int int wird, wird es 34.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top