значение 'const float' отличается от значения 'float' при приведении к 'int' в C#

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

  •  21-12-2019
  •  | 
  •  

Вопрос

Кто-нибудь из вас может объяснить, почему это происходит?

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

Выход:

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

Я знаю, что двоичное представление 0.1 на самом деле равно 0.09999990463256835937, хотя почему это происходит с использованием 'const float', а не с 'float'?Считается ли это ошибкой компилятора?

Для справки, код компилируется в:

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();
}
Это было полезно?

Решение

"Почему" этого в основном сводится к тому факту, что часто при работе с float данных, может использоваться внутреннее представление, обладающее большей точностью, чем указано для float или double.Это явно предусмотрено в спецификации виртуальной исполняющей системы (VES) (раздел 12 Раздел I):

числа с плавающей запятой представляются с использованием внутреннего типа с плавающей запятой.В каждом таком случае номинальным типом переменной или выражения является либо float32 или float64, но его значение может быть представлено внутренне с дополнительным диапазоном и/или точностью

А потом, позже, у нас есть:

Использование внутреннего представления, которое шире, чем float32 или float64 может привести к различиям в результатах вычислений, когда разработчик вносит, казалось бы, несвязанные изменения в свой код, результатом чего может быть перенос значения из внутреннего представления (например, в регистре) в местоположение в стеке.

Теперь, согласно Спецификация языка C#:

Вычисление константных выражений во время компиляции использует те же правила, что и вычисление непостоянных выражений во время выполнения, за исключением того, что там, где вычисление во время выполнения вызвало бы исключение, вычисление во время компиляции приводит к возникновению ошибки во время компиляции.

Но, как мы заметили выше, правила на самом деле позволяют время от времени использовать большую точность, и когда эта повышенная точность используется, на самом деле это не находится под нашим непосредственным контролем.


И очевидно, что при других обстоятельствах результаты могли бы быть прямо противоположными тому, что вы наблюдали - компилятор, возможно, снизил точность до более низкой, а среда выполнения могла бы вместо этого поддерживать более высокую точность.

Другие советы

Я не могу сказать, что это дубликат вопрос, так как здесь -> Eric Postpischil Comment

объяснил что-то очень похожее в отношении int и const int.

Основная идея состоит в том, что подразделение двух констант, рассчитанных на компилятор, прежде чем генерировать код, а не во время выполнения, но в этом конкретном случае всякий раз, когда компилятор делает это, он выполняет расчеты в DOQUE Формат.Таким образом, XSCalesizec в основном составляет 34,99999 ... поэтому, когда он становится литой во время выполнения, чтобы включить, он становится 34.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top