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

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

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

4

Решение

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

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

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

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

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

12

Другие решения

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

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

2

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

int m = a * b * c * d;

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

2

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

int m=a*b*c*d;

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

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

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

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

1
По вопросам рекламы [email protected]