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



как получилось, что в следующем фрагменте



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


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



так как int/int=double не работает?

844   8  

8 ответов:

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

c = a/(double)b;

вот это:

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

если вы хотите сохранить a и b как ints, но разделите их полностью, вы должны бросить хотя бы один из них, чтобы удвоить: (double)a/b или a/(double)b или (double)a/(double)b.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

c = a/(double)b

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

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

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

Comments

    Ничего не найдено.