Объяснение приведения/преобразования int/double в C#

Я закодировал некоторые вычисления (я скопировал ниже действительно упрощенный пример того, что я сделал), например CASE2, и получил плохие результаты. Рефакторинг кода как CASE1 и работал нормально. Я знаю, что в СЛУЧАЕ 2 есть неявное приведение, но не уверен в полной причине. Кто-нибудь может объяснить мне, что именно происходит ниже?

  //CASE 1, result 5.5
    double auxMedia = (5 + 6);
    auxMedia = auxMedia / 2;

    //CASE 2, result 5.0
    double auxMedia1 = (5 + 6) / 2;

    //CASE 3, result 5.5
    double auxMedia3 = (5.0 + 6.0) / 2.0;

    //CASE 4, result 5.5
    double auxMedia4 = (5 + 6) / 2.0;

Я предполагаю, что /2 в CASE2 приводит (5 + 6) к int и приводит к раунду деления до 5, затем снова приводится к удвоению и преобразуется в 5.0.

CASE3 и CASE 4 также устраняют проблему.


person Oscar Foley    schedule 31.03.2010    source источник
comment
В качестве примечания; здесь во время выполнения выполняется только одна операция. /2 в случае 1. Все остальное делает компилятор.   -  person Marc Gravell    schedule 31.03.2010
comment
@Marc: не может ли компилятор даже полностью выполнить случай 1 во время компиляции, поскольку auxMedia является локальным и назначается константой? Или это оптимизация, которую строго выполняет JIT?   -  person Michael Burr    schedule 31.03.2010
comment
@Michael - я бы ожидал, что это останется на усмотрение JIT. Чтобы ответить на него, вам нужно посмотреть на разные выходные данные компилятора...   -  person Marc Gravell    schedule 01.04.2010
comment
@Marc - я думаю, мне интересно, может ли спецификация C # по какой-то причине запретить подобную оптимизацию. В стандартах C/C++ есть целое понятие правила "как если бы", которое иногда вызывает путаницу. Я мог видеть, что разработчики C# могут захотеть отказаться от правила «как если бы», потому что они могут перенести эти оптимизации в JIT/среду выполнения. Это все просто бессвязное из любопытства, практически не применимое (я думаю).   -  person Michael Burr    schedule 01.04.2010


Ответы (4)


  1. 5 + 6 равно целому числу 11; который вы затем удваиваете (в задании) и делите на два; 5,5
  2. 5 + 6 равно целому числу 11; целое число 11 / 2 = 5 в целочисленной арифметике, которое вы затем приводите к удвоению (в задании)
  3. 5,0 + 6,0 удваивается 11,0; делим на удвоение 2,0, получаем удвоение 5,5
  4. 5 + 6 равно целому числу 11; есть неявное приведение к удвоению 11,0 для деления, затем деление на двойное 2,0 дает двойное 5,5
person Marc Gravell    schedule 31.03.2010
comment
Марк прав. Если ваша вторая строка была auxMedia = auxMedia / 2.0, то вы получите ожидаемый результат, поскольку 2.0 читается как двойное число, а 2 читается как целое (оно отбрасывает любые десятичные цифры - даже не округляется). - person Jaxidian; 31.03.2010

Чтобы немного расширить (правильный) ответ Марка, целые числа интерпретируются как целые числа, тогда как числа с десятичными точками интерпретируются как двойные. Чтобы объявить целое число буквальным двойным, добавьте к нему букву «D»:

        //CASE 2b, result 5.5
        double auxMedia2b = (5D + 6D) / 2;
person Jamie Ide    schedule 31.03.2010

Ты прав. СЛУЧАЙ 2 использует целочисленную арифметику до тех пор, пока не будет выполнено присвоение. Вы также можете решить проблему, выполнив явное приведение типов:

double auxMedia1 = ((double) (5 + 6)) / 2;
person Keltex    schedule 31.03.2010

//CASE 2, result 5.0
double auxMedia1 = (5 + 6) / 2;

Результат операции (5 + 6) является целым числом. Поскольку оба операнда имеют целочисленный тип. Затем компилятор выполняет 11/2, где оба операнда также являются целыми числами. Результат последнего деления, очевидно, равен 5, потому что это целочисленное деление (не знаю правильного английского слова).

person n535    schedule 31.03.2010