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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With