6

What's the order C++ does in chained multiplication ?

int a, b, c, d;
// set values
int m = a*b*c*d;
gsamaras
  • 71,951
  • 46
  • 188
  • 305
ampawd
  • 968
  • 8
  • 26
  • 4
    Didn't they mention at school that multiplication is commutative? – Jon Jul 25 '15 at 20:48
  • 9
    @Jon The relevant property is associativity, not commutativity. And school arithmetic is not immediately applicable here: `int` types are not the integers we use in mathematics, all operations are modulo 2^N. It just so happens that this doesn't damage the associativity for `unsigned` types, but signed integer overflow is undefined behavior and *float* multiplication isn't associative (neither is addition). –  Jul 25 '15 at 20:52
  • 1
    @jon i think your comment is meaningless, letting you know that for matrixes a*b != b*a !! so this is the actual reason I asked a question – ampawd Jul 25 '15 at 20:57
  • @arammis Matrix multiplication is associative though. –  Jul 25 '15 at 20:59
  • @arammis: Actually no, they give the same result, but anyway. You could make the context more clear if you did anything other than labelling those as `int` -- for example, saying "assume that a, b, c are user-defined types that overload the multiplication operator". – Jon Jul 25 '15 at 21:03
  • @Jon what gives same result ??? for integers yes it is the same, but not for maxtrixes, and my question is c++ language specific not school OKAY? – ampawd Jul 25 '15 at 21:11
  • @delnan I'm taking about the order not the associativity or commutativity – ampawd Jul 25 '15 at 21:17
  • @arammis Yes, you're talking about the order of parentheses. But if the operation is associative, the order does not matter (i.e., `a * (b * c)` is the same as `(a * b) * c`), therefore matrices are a bad example for why this order matters. –  Jul 25 '15 at 21:42
  • @delnan yea I know martices mult is assosiative, but I thought compiler may do b*a instead of a*b ... – ampawd Jul 26 '15 at 09:48
  • Possible duplicate of [Order of commutative mathematical operations](https://stackoverflow.com/q/49506802/608639), [C/C++ Math Order of Operation](https://stackoverflow.com/q/11296854/608639), [What are the rules governing C++ single and double precision mixed calculations?](https://stackoverflow.com/q/4239770/608639), [Order of operations to maximize precision](https://stackoverflow.com/q/45524072/608639), etc. – jww Mar 27 '18 at 07:47

5 Answers5

15

operator * has left to right associativity:

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

While in math it doesn't matter (multiplication is associative), in case of both C and C++ we may have or not have overflow depending on the order.

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

And things are getting even more complex if we consider floating point types or operator overloading. See comments of @delnan and @melpomene.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
AlexD
  • 32,156
  • 3
  • 71
  • 65
  • 1
    But it does not matter – Ed Heal Jul 25 '15 at 20:49
  • @EdHeal What if you have an overloaded `operator*`? Then it would matter. – melpomene Jul 25 '15 at 20:51
  • Yes - but the question at hand is to do with ints. Anyway should it not behave the same?! – Ed Heal Jul 25 '15 at 20:52
  • 12
    @EdHeal No, the question is about `*` in general. The example just happens to use `int`. And even with `int` it matters because of overflow: `0 * INT_MAX * INT_MAX`. If `INT_MAX * INT_MAX` is done first, it overflows, causing undefined behavior; but if `0 * INT_MAX` is done first, the result is simply 0. – melpomene Jul 25 '15 at 20:53
  • Am I reading a different question - or are you reading something more into the question – Ed Heal Jul 25 '15 at 20:55
  • @melpomene Thanks! I added it to the answer, hopefully you do not mind. (I was about to make the same remark about overflow, but was checking the standard, and found that you did it already.) – AlexD Jul 25 '15 at 21:14
  • 1
    @EdHeal: You seem to be reading a different question; this one is quite clear. – Lightness Races in Orbit Jul 25 '15 at 21:26
2

Yes, the order is from left to right.

int m = a * b * c * d;

If you are more interested in the topic of evaluation order or operator precedence, then you might be surprised how some ++ operations behave, even differently with the version of C.

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

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

adamliesko
  • 1,887
  • 1
  • 14
  • 21
2

The order is from left to right in this case where

int m=a*b*c*d;

Here, first (a*b) is computed then the result is multiplied by c and then d as shown using parentheses:

int m=(((a*b)*c)*d);
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
2

The order is nominally left to right. But the optimizers in C++ compilers I've used feel free to change that order for data types they think they understand. If you overload operator* and the optimizer can't see through your overload, then it can't change the order. But when you multiply a sequence of things (variables, constants, function results, etc.) whose type is double, the optimizer might use the associative and commutative property of real number multiplication as if it were true in float or double multiplication. That can lead to some surprises when least significant bits matter to you.

So far as I understand, the standard allows that optimization, but I am far from a "language lawyer" so my best guess on the standard is not a pronouncement to be trusted (as compared with my experience on what compilers actually do).

JSF
  • 5,281
  • 1
  • 13
  • 20
  • 2
    If the optimizer rearranges evaluation order of floating point operators, it is violating the standard so you should report it as a bug. "Operators can be regrouped according to the usual mathematical rules only where the operators really are associative or commutative." (1.9/p.9). – rici Jul 25 '15 at 23:05
1

There isn't any special "order" it multiplies as shown, left to right.

int m = a * b * c * d;

The order of operations comes into affect when using addition/ subtraction with dividing/ multiplying. Otherwise it is always left to right. Regardless, with the example, the solution would be the same no matter which order they were in.

Evan Carslake
  • 2,267
  • 15
  • 38
  • 56
  • 7
    If "it multiplies as shown, left to right", then that is an order. – melpomene Jul 25 '15 at 20:57
  • 6
    _"Regardless, with the example, the solution would be the same no matter which order they were in"_ Hmm, what about overflow, which may happen or not depending on the order? – AlexD Jul 25 '15 at 21:17