Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is arithmetic commutative and associative?

Tags:

c#

.net

math

In maths, addition (of real numbers) is commutative and associative, ie. for all numbers x, y and z

x + y = y + x (commutativity)

and

x + (y + z) = (x + y) + z (associativity)

Multiplication of real numbers is also commutative and associative. But is this true for ints and floats in .NET? Counterexamples welcome.

Edit: Background is we've recently parallelised an algorithm and now its results are no longer consistent between repeats. I speculate this might be due to the atomic calculations returning (and being merged) in non-deterministic order. In which case, the inconsistency could be fixed by a smarter (but slower) merge algorithm (that sorts the results before merging). I'd like to know what assumptions it can make about .NET arithmetic.

like image 446
Colonel Panic Avatar asked Oct 14 '13 11:10

Colonel Panic


1 Answers

Assuming no unchecked overflows occur, .NET's integer addition and multiplication (int, long, etc.) is commutative and associative, like the real numbers in math. Floating point arithmetic (float and double) is commutative, but not always precisely associative, due to the limits of precision. From Wikipedia (with an example in the article):

While floating-point addition and multiplication are both commutative (a + b = b + a and a×b = b×a), they are not necessarily associative. That is, (a + b) + c is not necessarily equal to a + (b + c).

Here's an example:

a: 0.825402526103613
b: 0.909231618470155
c: 0.654626872695343
(a*b)*c: 0.491285733573819
a*(b*c): 0.49128573357382

There are some examples where the results appear the same when turned into a string, but are different ((a*b)*c != a*(b*c) is true, and (a*b)*c - a*(b*c) returns a small value, not 0).

a: 0.613781429181705
b: 0.648859122604532
c: 0.795545351596337
(a*b)*c: 0.316832045751117
a*(b*c): 0.316832045751117
difference: 5.55111512312578E-17
like image 139
Tim S. Avatar answered Sep 30 '22 04:09

Tim S.