Подтвердить что ты не робот

Почему разделение двух int не дает правильного значения при присвоении двойной?

Как это происходит в следующем фрагменте

int a = 7;
int b = 3;
double c = 0;
c = a / b;

c заканчивается тем, что имеет значение 2, а не 2.3333, как и следовало ожидать. Если a и b являются двойниками, ответ переходит к 2.333. Но, конечно, потому что c уже является двойным, он должен работать с целыми числами?

Итак, почему int/int=double не работает?

4b9b3361

Ответ 1

Это потому, что вы используете версию с целым делением operator/, которая принимает 2 int и возвращает int. Чтобы использовать версию double, которая возвращает double, по крайней мере один из int должен быть явно ливан в double.

c = a/(double)b;

Ответ 2

Вот он:

a) Разделение двух int выполняет целочисленное деление всегда. Таким образом, результат a/b в вашем случае может быть только int.

Если вы хотите сохранить a и b как int s, но разделите их полностью, вы должны сделать хотя бы один из них двойным: (double)a/b или a/(double)b или (double)a/(double)b.

b) c является double, поэтому он может принимать значение int при назначении: int автоматически преобразуется в double и присваивается c.

c) Помните, что при назначении сначала вычисляется выражение справа от = (в соответствии с правилом (a) выше и без учета переменной слева от =), а затем назначается переменная слева от = (согласно (б) выше). Я считаю, что это завершает картину.

Ответ 3

За очень немногими исключениями (я могу думать только об одном), С++ определяет весь смысл выражения (или подвыражения) из выражения сам. То, что вы делаете с результатами выражения, не имеет значения. В вашем случае в выражении a / b нет double в взгляд; все int. Поэтому компилятор использует целочисленное деление. Только после того, как он имеет результат, он рассматривает, что с ним делать, и преобразуйте его в double.

Ответ 4

Когда вы делите два целых числа, результат будет целым, независимо от того, что вы храните его в двойном.

Ответ 5

c - это переменная double, но назначаемое ей значение является значением int, поскольку оно возникает из-за деления двух int s, что дает вам "целочисленное деление" (отбрасывание остатка). Итак, что происходит в строке c=a/b, есть

  • a/b оценивается, создавая временный тип int
  • значение временного присваивается c после преобразования в тип double.

Значение a/b определяется без ссылки на его контекст (присвоение double).

Ответ 6

Оператор / может использоваться для деления целочисленного деления или с плавающей запятой. Вы даете ему два целочисленных операнда, поэтому он выполняет целочисленное деление, а затем результат сохраняется в double.

Ответ 7

В языке С++ результат субэкспозиции никогда не затрагивается окружающим контекстом (за некоторыми редкими исключениями). Это один из принципов, которым следует следовать на этом языке. Выражение c = a / b содержит независимое подвыражение a / b, которое интерпретируется независимо от чего-либо вне этого подвыражения. Язык не заботится о том, чтобы вы позже присвоили результат double. a / b - целочисленное деление. Все остальное не имеет значения. Вы увидите, что этот принцип соблюдается во многих уголках спецификации языка. Это говорит о том, как работает С++ (и C).

Одним из примеров исключения, о котором я упоминал выше, является назначение/инициализация указателя функции в ситуациях с перегрузкой функции

void foo(int);
void foo(double);

void (*p)(double) = &foo; // automatically selects `foo(fouble)`

Это один из контекстов, где левая часть присваивания/инициализации влияет на поведение правой части. (Кроме того, инициализация ссылочного массива предотвращает распад типа массива, что является еще одним примером аналогичного поведения.) Во всех остальных случаях правая часть полностью игнорирует левую сторону.

Ответ 8

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

При делении двух чисел одного и того же типа (целые числа, удваивания и т.д.) результат всегда будет одного типа (так что "int/int" всегда будет иметь значение int).

В этом случае у вас есть double var = integer result который после вычисления вычисляет целочисленный результат в double, и в этом случае дробные данные уже теряются. (большинство языков сделает это кастинг, чтобы предотвратить неточности типов, не создавая исключения или ошибки).

Если вы хотите сохранить результат как двойной, вам захочется создать ситуацию, в которой вы double var = double result

Самый простой способ сделать это - заставить выражение с правой стороны уравнения сбрасывать двойным:

c = a/(double)b

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

После перегрева a закончится как двойной, и теперь у вас есть разделение между двумя удвоениями. Это создаст желаемое деление и назначение.

AGAIN,, обратите внимание, что это специфичный для языка (и может даже быть специфичным для компилятора), однако почти все языки (конечно, все, что я могу придумать с головы) рассматривают это Пример идентичен.