Позволяет ли удвоить удвоение каждого int в уравнении?
Означает ли наличие одного типа данных с плавающей точкой (например, double
), что все операции m +, -, *,/,% и т.д. принимают двойные операнды?
Если история сложнее, есть ли ресурс, описывающий эти правила? Должен ли я не задавать такие вопросы и всегда явно отбрасывать int
до double
, когда результат уравнения равен double
. Вот некоторые уравнения, о которых я думаю. Я целенаправленно не компилировал и не запускал тогда в своей системе, поскольку это тот тип вещи, который может быть зависимым от компилятора.
int a(1), b(2), c(3);
double d(4.);
double result1 = a + b/d + c; // equal to 4 or to 4.5?
double result2 = (a + b)/d + c; // equal to 3 or to 3.75?
double result3 = a/b + d; // equal to 4 or to 4.5?
Ответы
Ответ 1
Я целенаправленно не компилировал и не запускал его в своей системе, поскольку это тот тип вещи, который может быть зависимым от компилятора.
Это зависит от компилятора не. С++ четко определяет порядок этих операций и то, как они преобразуются.
Как происходит преобразование, зависит от порядка операций.
double result1 = a + b / d + c; // equal to 4 or to 4.5?
В этом примере сначала происходит деление. Поскольку это int, разделенный на double, компилятор обрабатывает это, преобразовывая int в double. Таким образом, результат b / d
является двойным.
Следующее, что делает С++, - это добавить a
к результату b / d
. Это int добавлено в double, поэтому он преобразует int в double и добавляет, что приводит к двойному. То же самое происходит с c
.
double result3 = a / b + d; // equal to 4 or to 4.5?
В этом примере деление обрабатывается первым. a
и b
- оба int, поэтому преобразование не выполняется. Результат a / b
имеет тип int и равен 0.
Затем результат этого добавляется к d
. Это int plus double, поэтому С++ преобразует int в double, а результат - double.
Даже если в этом выражении присутствует двойник, сначала оценивается a / b
, а double означает ничего, пока выполнение не достигнет double. Поэтому происходит целочисленное деление.
Я считаю, что правила продвижения и конвертации довольно сложны. Обычно целочисленные числа (short, int, long) продвигаются к эквивалентам с плавающей запятой (float, double). Но вещи осложняются различиями в размерах и знаками.
Подробнее о преобразовании см. этот вопрос.
Ответ 2
Поддерживает ли double
каждый int
в уравнении до double
?
Нет. Только результат одной операции (относительно приоритета).
double result1 = a + b/d + c; // equal to 4 or to 4.5?
4.5.
double result2 = (a + b)/d + c; // equal to 3 or to 3.75?
3,75.
double result3 = a/b + d; // equal to 4 or to 4.5?
4.
Ответ 3
Вы должны учитывать приоритет каждого оператора, вы должны думать как синтаксический анализатор:
double result1 = a + b/d + c; // equal to 4 or to 4.5?
Это похоже на + (b/d) + c, потому что оператор "/" имеет наибольший приоритет. Тогда не имеет значения, что из этих двух операций выполняется для первого, поскольку операнд с плавающей запятой находится в середине, и он "заражает" другие операнды и делает их двойными. Итак, 4.5.
double result2 = (a + b)/d + c; // equal to 3 or to 3.75?
То же самое здесь, это как ((a + b)/d) + c, поэтому a + b равно 3, что 3 становится числом с плавающей запятой, потому что получает повышение до double, потому что это дивиденд d, который является double, поэтому 0,75 + 3, то есть 3,75.
double result3 = a/b + d; // equal to 4 or to 4.5?
Это похоже на (a/b) + d, поэтому a/b равно нулю, а d равно 4, поэтому оно 4.
Парсер делает все операции в порядке приоритета, поэтому вы можете точно знать, что будет результатом выражения.
Ответ 4
В общем случае, если один операнд двоичного оператора является плавающей точкой, а другой является целым числом, целое число преобразуется в плавающую точку, а результат - с плавающей запятой.
В составном выражении с несколькими подвыражениями каждый оператор обрабатывается индивидуально, используя правила приоритета, которые вы, вероятно, знаете. Таким образом, в a*b + c*d
оценивается a*b
и оценивается c*d
, и результаты складываются вместе. Все, что находится в c*d
, не действует в a*b
и наоборот.
C++, конечно, сложна, и пользовательские операторы могут иметь другие типы поведения.
Авторитетным ресурсом, определяющим правила, является стандарт С++. Стандарт довольно большой и технический. Сначала вы можете сначала изучить стандарт C. См. этот ответ для ссылок на стандарты. Любая хорошая книга на C или С++ должна описывать преобразования типов по умолчанию и оценку выражения.