El valor de 'const float' es diferente de 'float' cuando se convierte a 'int' en C#

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

  •  21-12-2019
  •  | 
  •  

Pregunta

¿Alguno de ustedes puede explicar por qué sucede esto?

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

Producción:

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

Sé que la representación binaria de 0,1 es en realidad 0,09999990463256835937, aunque ¿por qué sucede esto usando 'const float' y no con 'float'?¿Se considera esto un error del compilador?

Para que conste, el código se compila 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();
}
¿Fue útil?

Solución

El "por qué" de esto básicamente se reducirá al hecho de que frecuentemente, cuando se trabaja con float datos, se puede utilizar una representación interna que tenga más precisión que la especificada para float o double.Esto se contempla explícitamente en la especificación del sistema de ejecución virtual (VES) (sección 12 de Partición I):

Los números de punto flotante se representan utilizando un tipo interno de punto flotante.En cada uno de estos casos, el tipo nominal de la variable o expresión es float32 o float64, pero su valor se puede representar internamente con rango adicional y/o precisión

Y luego tenemos:

El uso de una representación interna que sea más amplia que float32 o float64 Puede causar diferencias en los resultados computacionales cuando un desarrollador realiza modificaciones aparentemente no relacionadas con su código, cuyo resultado puede ser que se derrama un valor desde la representación interna (por ejemplo, en un registro) a una ubicación en la pila.

Ahora bien, según el Especificación del lenguaje C#:

La evaluación en tiempo de compilación de expresiones constantes utiliza las mismas reglas que la evaluación en tiempo de ejecución de expresiones no constantes, excepto que cuando la evaluación en tiempo de ejecución habría generado una excepción, la evaluación en tiempo de compilación provoca que se produzca un error en tiempo de compilación.

Pero como observamos anteriormente, las reglas en realidad permiten que se use más precisión en ocasiones, y cuando se usa esta precisión mejorada no está realmente bajo nuestro control directo.


Y obviamente, en diferentes circunstancias, los resultados podrían haber sido exactamente lo contrario de lo que observó: es posible que el compilador haya bajado a una precisión más baja y el tiempo de ejecución podría haber mantenido una precisión más alta.

Otros consejos

No puedo decir que esta es una pregunta duplicada desde aquí -> Eric Postpischil comment

Explicó algo muy similar con respecto a INT y Const Int's.

La idea principal es que la división de dos constantes calculada por el compilador antes de generar el código y no en tiempo de ejecución, pero en este caso específico, siempre que el compilador haga esto, realiza los cálculos en doble Formato.Por lo tanto, la XSCalesizec es básicamente igual a 34.9999 ... así que cuando se lanza en tiempo de ejecución para intentarlo en 34.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top