Question

L'un d'entre vous peut-il expliquer pourquoi cela se produit ?

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();
}

Sortir:

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

Je sais que la représentation binaire de 0,1 est en fait 0,09999990463256835937, mais pourquoi cela se produit-il en utilisant « const float » et non avec « float » ?Est-ce considéré comme un bug du compilateur ?

Pour mémoire, le code se compile en :

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();
}
Était-ce utile?

La solution

Le « pourquoi » se résumera essentiellement au fait que, fréquemment, lorsque l'on travaille avec float données, une représentation interne peut être utilisée avec plus de précision que celle spécifiée pour float ou double.Ceci est explicitement pris en compte dans la spécification du système d'exécution virtuelle (VES) (section 12 de Partition I):

Les nombres à virgule flottante sont représentés à l'aide d'un type interne à virgule flottante.Dans chacun de ces cas, le type nominal de la variable ou de l'expression est soit float32 ou float64, mais sa valeur peut être représentée en interne avec une plage et / ou une précision supplémentaires

Et puis plus tard nous avons :

L’utilisation d’une représentation interne plus large que float32 ou float64 Peut provoquer des différences dans les résultats de calcul lorsqu'un développeur apporte des modifications apparemment indépendantes à son code, dont le résultat peut être qu'une valeur est renversée à partir de la représentation interne (par exemple, dans un registre) à un emplacement sur la pile.

Maintenant, selon le Spécification du langage C#:

L'évaluation au moment de la compilation des expressions constantes utilise les mêmes règles que l'évaluation au moment de l'exécution des expressions non constantes, sauf que là où l'évaluation au moment de l'exécution aurait levé une exception, l'évaluation au moment de la compilation provoque une erreur de compilation.

Mais comme nous l'avons observé ci-dessus, les règles permettent parfois d'utiliser plus de précision, et le moment où cette précision améliorée est utilisée n'est pas réellement sous notre contrôle direct.


Et évidemment, dans des circonstances différentes, les résultats auraient pu être exactement le contraire de ce que vous avez observé : le compilateur aurait pu baisser à une précision inférieure et le moteur d'exécution aurait pu maintenir une précision plus élevée.

Autres conseils

Je ne peux pas dire que ceci est une question en double depuis ici -> Eric Postpischil Commentaire

a expliqué quelque chose de très similaire concernant Int et const int's.

L'idée principale est que la division de deux constantes calculée par le compilateur avant de générer le code et non à l'exécution, mais dans ce cas spécifique chaque fois que le compilateur est celui-ci, il effectue les calculs dans double format.Ainsi, le xscalesizeC est fondamentalement égale à 34,9999 ... Donc, quand il se dépose dans le temps d'exécution pour qu'il devient 34.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top