Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are floating point operations in C associative?

Addition mathematically holds the associative property:

(a + b) + c = a + (b + c)

In the general case, this property does not hold for floating-point numbers because they represent values in a finite precision.

Is a compiler allowed to make the above substitution when generating machine code from a C program as part of an optimization? Where does it exactly say in the C standard?

like image 995
zr. Avatar asked Dec 17 '12 11:12

zr.


People also ask

Is floating-point associative?

In mathematics, addition and multiplication of real numbers is associative. By contrast, in computer science, the addition and multiplication of floating point numbers is not associative, as rounding errors are introduced when dissimilar-sized values are joined together.

Is floating-point multiplication commutative?

According to Wikipedia, yes, float multiplication is commutative. While floating-point addition and multiplication are both commutative (a + b = b + a and a×b = b×a), they are not necessarily associative.

Why is float addition not associative?

With floating-point operands, it is commutative but not associative. Thus, if you have two expressions that produce different results, you cannot form one from the other by applying only commutativity. @tmyklebu OK, so this does check associativity if and only if it is known that commutativity holds.

What is floating-point representation in C?

A "floating-point constant" is a decimal number that represents a signed real number. The representation of a signed real number includes an integer portion, a fractional portion, and an exponent. Use floating-point constants to represent floating-point values that can't be changed.


2 Answers

The compiler is not allowed to perform "optimizations", which would result in a different value computed, than the one computed according to abstract machine semantics.

5.1.2.3 Program execution

[#1] The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant.

[#3] In the abstract machine, all expressions are evaluated as specified by the semantics.

[#13] EXAMPLE 5 Rearrangement for floating-point expressions is often restricted because of limitations in precision as well as range. The implementation cannot generally apply the mathematical associative rules for addition or multiplication, nor the distributive rule, because of roundoff error, even in the absence of overflow and underflow.

In your example:

(a + b) + c

or even without the parentheses:

a + b + c

we have

   +
  / \
  +  c
 / \
 a  b

and the compiler is required to generate code as if a is summed with b and the result is summed with c.

like image 146
chill Avatar answered Oct 20 '22 13:10

chill


You can make floating point operations associative with the gcc options:

-funsafe-math-optimizations -O2

Example:

double test (double a, double b, double c) {    
  return (a + b + c) * (a + (b + c));
}

This is reduced to:

double temp = a + (b + c);
return temp * temp;

Similarly, (a + b + c) - (a + (b + c)) is reduced to zero, ignoring the possibility of INF and NAN.

If I compile with -fassociative-math -O2 instead, I get the weird message:

warning: -fassociative-math disabled; other options take precedence

The -funsafe-math-optimizations can improve speed if you don't care about the order of the operands anyway, but it may cause loss of precision if the order of operands is important, and you may lose NAN and INF results.

like image 30
A Fog Avatar answered Oct 20 '22 13:10

A Fog