CLCS

Examples of Associativity and Commutativity in Numeric Operations

Consider the following expression, in which we assume that 1.0 and 1.0e-15 both denote single floats:

 (+ 1/3 2/3 1.0d0 1.0 1.0e-15)

One conforming implementation might process the arguments from left to right, first adding 1/3 and 2/3 to get 1, then converting that to a double float for combination with 1.0d0, then successively converting and adding 1.0 and 1.0e-15.

Another conforming implementation might process the arguments from right to left, first performing a single float addition of 1.0 and 1.0e-15 (perhaps losing accuracy in the process), then converting the sum to a double float and adding 1.0d0, then converting 2/3 to a double float and adding it, and then converting 1/3 and adding that.

A third conforming implementation might first scan all the arguments, process all the rationals first to keep that part of the computation exact, then find an argument of the largest floating-point format among all the arguments and add that, and then add in all other arguments, converting each in turn (all in a perhaps misguided attempt to make the computation as accurate as possible).

In any case, all three strategies are legitimate.

A conforming program could control the order by writing, for example,

 (+ (+ 1/3 2/3) (+ 1.0d0 1.0e-15) 1.0)