Порядок умножений

Что делает C++ в цепочечном умножении?

int a, b, c, d;
// set values
int m = a*b*c*d;

5 ответов

Решение

Оператор * слева направо ассоциативность:

int m = ((a * b) * c) * d;

Хотя в математике это не имеет значения (умножение ассоциативно), в случае C и C++ мы можем иметь или не иметь переполнение в зависимости от порядка.

0 * INT_MAX * INT_MAX // 0
INT_MAX * INT_MAX * 0 // overflow

И все становится еще сложнее, если мы рассмотрим типы с плавающей запятой или перегрузку операторов. Смотрите комментарии @delnan и @melpomene.

Порядок слева направо в этом случае, где

int m=a*b*c*d;

Здесь сначала вычисляется (a*b), затем результат умножается на c, а затем d, как показано в скобках:

int m=(((a*b)*c)*d);

Не существует какого-либо специального "порядка", который он умножает, как показано слева направо.

int m = a * b * c * d;

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

Порядок номинально слева направо. Но оптимизаторы в компиляторах C++, которые я использовал, не стесняются изменять этот порядок для типов данных, которые, по их мнению, они понимают. Если вы перегрузите оператор *, а оптимизатор не сможет увидеть вашу перегрузку, он не сможет изменить порядок. Но когда вы умножаете последовательность вещей (переменные, константы, результаты функций и т. Д.), Тип которых двойной, оптимизатор может использовать ассоциативное и коммутативное свойство умножения действительного числа, как если бы оно было истинным при умножении с плавающей запятой или двойном умножении. Это может привести к некоторым неожиданностям, когда для вас важны наименее значимые биты.

Насколько я понимаю, стандарт допускает такую ​​оптимизацию, но я далеко не "языковой адвокат", поэтому мое лучшее предположение о стандарте - это не заявление, которому нужно доверять (по сравнению с моим опытом в том, что на самом деле делают компиляторы).

Да, порядок слева направо.

int m = a * b * c * d;

Если вас больше интересует тема порядка вычисления или приоритета операторов, вы можете быть удивлены, как ведут себя некоторые операции ++, даже по-разному с версией C.

http://en.cppreference.com/w/c/language/eval_order

http://en.cppreference.com/w/c/language/operator_precedence

Другие вопросы по тегам