Как C# оценивает плавающую точку в парении и непосредственном окне по сравнению со скомпилированным?

Краткость.

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

7
задан Sergey 30 August 2019 в 18:14
поделиться

4 ответа

Это проблема с плавающей точностью.

Второй оператор работает, потому что компилятор считает выражение 1e-3 * 1e3 перед выдачей .exe.

Посмотрите его в ILDasm / Reflector, он выдаст что-то вроде

 if (1.0 < 1.0)
                Console.WriteLine("Wrong");
13
ответ дан 6 December 2019 в 08:44
поделиться

Проблема здесь довольно тонкая. Компилятор C # не (всегда) генерирует код, который выполняет вычисления с двойной точностью, даже если это тот тип, который вы указали. В частности, он генерирует код, который выполняет вычисления с «расширенной» точностью с использованием инструкций x87, без округления промежуточных результатов до удвоения.

В зависимости от того, оценивается ли 1e-3 как двойное или длинное двойное, и вычисляется ли умножение в double или long double можно получить любой из следующих трех результатов:

  • (long double) 1e-3 * 1e3, вычисленное в long double, равно 1.0 - epsilon
  • (double) вычислено 1e-3 * 1e3 in double равно 1.0
  • (double) 1e-3 * 1e3, вычисленное в long double, равно 1.0 + epsilon

Очевидно, первое сравнение, тот, который не оправдывает ваши ожидания, оценивается в порядке, описанном в третьем сценарии, который я перечислил. 1e-3 округляется до удвоения либо потому, что вы сохраняете его и загружаете снова, что вызывает округление, либо потому, что C # распознает 1e-3 как литерал с двойной точностью и обрабатывает его таким образом. Умножение оценивается как long double, потому что C # имеет безумную числовую модель , именно так компилятор генерирует код.

Умножение во втором сравнении либо оценивается с использованием одного из два других метода (вы можете выяснить, какой из них, попробовав «1> 1e-3 * 1e3»), или компилятор округляет результат умножения, прежде чем сравнивать его с 1.0, когда он оценивает выражение во время компиляции.

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

4
ответ дан 6 December 2019 в 08:44
поделиться

См. Ответы здесь

2
ответ дан 6 December 2019 в 08:44
поделиться

Ммм ... странно. Я не могу воспроизвести вашу проблему. Я также использую C # 3.5 и Visual Studio 2008. Я набрал в вашем примере точно , как он был опубликован, и я не вижу выполнения ни одного оператора Console.WriteLine .

Кроме того, второй оператор if оптимизируется с помощью компилятор. Когда я исследую как отладочную, так и выпускную сборки в ILDASM / Reflector, я не вижу никаких свидетельств этого. Это происходит потому, что я получаю предупреждение компилятора о том, что на нем обнаружен недостижимый код.

Наконец, я не понимаю, как это могло быть проблемой точности с плавающей запятой. Почему компилятор C # статически оценивает два двойных значения иначе, чем CLR во время выполнения? Если бы это было действительно так, то можно было бы привести аргумент, что в компиляторе C # есть ошибка.

Изменить: Поразмыслив еще немного, я еще больше убедился, что это не проблема точности с плавающей запятой. Вы, должно быть, наткнулись на ошибку в компиляторе или отладчике, или опубликованный вами код не совсем соответствует вашему действительному запущенному коду. Я очень скептически отношусь к ошибке в компиляторе, но ошибка в отладчике кажется более вероятной. Попробуйте пересобрать проект и запустить его снова. Возможно, отладочная информация, скомпилированная вместе с exe, рассинхронизировалась или что-то в этом роде.

Я очень скептически отношусь к ошибке в компиляторе, но ошибка в отладчике кажется более вероятной. Попробуйте пересобрать проект и запустить его снова. Возможно, отладочная информация, скомпилированная вместе с exe, рассинхронизировалась или что-то в этом роде.

Я очень скептически отношусь к ошибке в компиляторе, но ошибка в отладчике кажется более вероятной. Попробуйте пересобрать проект и запустить его снова. Возможно, отладочная информация, скомпилированная вместе с exe, рассинхронизировалась или что-то в этом роде.

2
ответ дан 6 December 2019 в 08:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: