Как получилось, что в следующем фрагменте
int a = 7;
int b = 3;
double c = 0;
c = a / b;
c
в конечном итоге получает значение 2, а не 2.3333, как можно было бы ожидать. Если a
и b
являются двойными, то ответ действительно равен 2,333. Но наверняка, потому что c
уже есть двойник, он должен был работать с целыми числами?
Так почему int/int=double
же не работает?
Ответы:
Это связано с тем, что вы используете версию с целочисленным делением
operator/
, которая занимает 2int
с и возвращаетint
. Чтобы использоватьdouble
версию, которая возвращает adouble
, по крайней мере один изint
s должен быть явно приведен к adouble
.источник
a
иb
вdouble
просто для ясности, но на самом деле это не имеет значения.static_cast<>
мне всегда казалось, что надо запыхаться. В случае примитивов, не существует на самом деле никакой опасности получатьstatic_cast<>
иreinterpret_cast<>
перепутаны.static_cast
этого и вместо этого использовать приведение в стиле C. Здесь нет никакой пользы от использования приведения в стиле C ++, и они загромождают код намного больше, чем приведения в стиле C. Арифметическое приведение - это именно тот контекст, в котором приведение в стиле C совершенно уместно и фактически более уместно, чем другие приведения.double(b)
. Они не всегда понимают, что это преобразование, поскольку оно выглядит так же, как явный вызов конструктора.Вот:
а) При
int
делении на два всегда выполняется целочисленное деление. Так что результатомa/b
в вашем случае может быть только файлint
.Если вы хотите сохранить
a
иb
какint
s, но при этом полностью разделить их, вы должны преобразовать хотя бы одно из них в двойное:(double)a/b
илиa/(double)b
или(double)a/(double)b
.б)
c
являетсяdouble
, поэтому он может принять вint
значение на присваивания:int
автоматически преобразуютсяdouble
и назначеноc
.c) Помните, что при присваивании сначала
=
вычисляется выражение справа от (в соответствии с правилом (a) выше и без учета переменной слева от ), а затем присваивается переменной слева от (согласно ( б) выше). Я считаю, что это завершает картину.=
=
источник
За очень немногими исключениями (я могу придумать только одно) C ++ определяет полное значение выражения (или подвыражения) из самого выражения. Что вы делаете с результатами выражения, не имеет значения. В вашем случае в выражении
a / b
нет иdouble
видно; все естьint
. Таким образом, компилятор использует целочисленное деление. Только получив результат, он решает, что с ним делать, и преобразует его вdouble
.источник
&funcname
зависит от того, к какому типу вы его приводите .c
-double
переменная, но присвоенное ейint
значение является значением, потому что оно получается в результате деления на дваint
s, что дает вам «целочисленное деление» (отбрасывание остатка). Итак, что происходит в строкеc=a/b
,a/b
оценивается, создавая временный типint
c
после преобразования в типdouble
.Значение
a/b
определяется без привязки к его контексту (присвоениеdouble
).источник
Когда вы делите два целых числа, результатом будет целое число, независимо от того, что вы сохраняете его в двойном формате.
источник
В языке C ++ на результат подвыражения никогда не влияет окружающий контекст (за некоторыми редкими исключениями). Это один из принципов, которым тщательно следует язык. Выражение
c = a / b
содержит независимое подвыражениеa / b
, которое интерпретируется независимо от всего, что находится за пределами этого подвыражения. Язык не заботится о том, что вы позже назначите результат дляdouble
.a / b
является целочисленным делением. Все остальное не имеет значения. Вы увидите, что этому принципу следуют во многих уголках спецификации языка. Вот и все, как работает C ++ (и C).Одним из примеров исключения, упомянутого выше, является назначение / инициализация указателя функции в ситуациях с перегрузкой функции.
Это тот контекст, в котором левая часть присвоения / инициализации влияет на поведение правой части. (Кроме того, инициализация ссылки на массив предотвращает распад типа массива, что является еще одним примером аналогичного поведения.) Во всех других случаях правая часть полностью игнорирует левую часть.
источник
/
Оператор может быть использован для целочисленного деления или деления с плавающей точкой. Вы даете ему два целочисленных операнда, поэтому он выполняет целочисленное деление, а затем результат сохраняется в виде двойника.источник
Технически это зависит от языка, но почти все языки относятся к этому предмету одинаково. Когда существует несоответствие типов между двумя типами данных в выражении, большинство языков будет пытаться преобразовать данные с одной стороны,
=
чтобы они соответствовали данным с другой стороны, в соответствии с набором предопределенных правил.При делении двух чисел одного типа (целые числа, числа с двойной точностью и т. Д.) Результат всегда будет одного и того же типа (поэтому 'int / int' всегда будет иметь результатом int).
В этом случае у вас есть
double var = integer result
функция, которая преобразует целочисленный результат в двойной после вычисления, и в этом случае дробные данные уже потеряны. (большинство языков делают это преобразование, чтобы предотвратить неточности типов, не вызывая исключения или ошибки).Если вы хотите сохранить результат как двойной, вам нужно создать ситуацию, когда у вас есть
double var = double result
Самый простой способ сделать это - заставить выражение в правой части уравнения преобразоваться в двойное:
c = a/(double)b
Разделение между целым числом и числом double приведет к преобразованию целого числа в число double (обратите внимание, что при выполнении математических операций компилятор часто выполняет преобразование с повышением частоты до наиболее определенного типа данных, чтобы предотвратить потерю данных).
После апкаста
a
будет двойной, и теперь у вас есть деление на два дубля. Это создаст желаемое разделение и назначение.СНОВА, пожалуйста , обратите внимание, что это зависит от языка (и может быть даже от компилятора), однако почти все языки (конечно, все те, которые я могу придумать в своей голове) относятся к этому примеру одинаково.
источник
Главное, чтобы один из элементов расчета был типом float-double. Затем, чтобы получить двойной результат, вам нужно привести этот элемент, как показано ниже:
или c = a / static_cast (b);
Или вы можете создать его напрямую:
Обратите внимание, что один из элементов расчета должен иметь значение '.0', чтобы указать деление типа float-double на целое число. В противном случае, несмотря на то, что переменная c является двойной, результат тоже будет нулевым.
источник