У меня возник интересный вопрос (я задаю его сам, читая сырой кусок кода). Давайте посмотрим на выражение:
double a = c*d*e*2/3*f;
где c, d, e, f — инициализированные переменные типа double
, Стандартная гарантия, что это будет рассматриваться как c*d*e*2
(двойной результат) затем делится на 3
и умножить на f
(или похожее поведение). Очевидно, что 2/3, рассчитываемое на 0, нежелательно.
Какой параграф стандарта определяет это?
На основе стандарт
[intro.abstract] — Примечание 7 (Ненормативные):
Операторы могут быть перегруппированы в соответствии с обычными математическими правилами
только там, где операторы действительно ассоциативны или коммутативны.
Математическое правило для MDAS слева направо (с учетом ассоциативности и приоритета операторов). Так это оценивается следующим образом:
(((((c * d) * e) * 2) / 3) * f)
Одним словом — да.
Свойство, которое вы ищете, называется ассоциативностью операторов. Он определяет, как операторы с одинаковым приоритетом (например, *
а также /
) группируются и упорядочиваются при отсутствии скобок.
В вашем случае оба *
а также /
имеют одинаковый приоритет и оба являются левоассоциативными — то есть они оцениваются слева направо. Что значит c
будет умножено на d
то результат по e
то результат по 2
(что будет сделано с помощью арифметики с плавающей запятой, так как вы умножаете double
по int
буквально), затем делится на 3
(снова с использованием арифметики с плавающей запятой) и, наконец, умножается на f
,
Увидеть эта страница cppreference для дополнительной информации.
И то и другое *
а также /
имеют одинаковый приоритет и являются ассоциативными слева направо, это означает, что
a*b*c*d
анализируется как
((a*b)*c)*d
и то же самое верно, если вы замените любой из *
с /
,
Источник: http://en.cppreference.com/w/cpp/language/operator_precedence