значение 'const float' отличается от значения 'float' при приведении к 'int' в C#
-
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.
Основная идея состоит в том, что подразделение двух констант, рассчитанных на компилятор, прежде чем генерировать код, а не во время выполнения, но в этом конкретном случае всякий раз, когда компилятор делает это, он выполняет расчеты в