Skip to main content

PWR046: Replace two divisions with a division and a multiplication

Issue

Divisions are expensive operations on modern hardware, so replacing them with cheaper operations can often improve performance.

Actions

Replace a double division with a division and a multiplication.

Relevance

Double divisions can be replaced with a division and multiplication, according to the following patterns:

  • (a / b) / c = a / (b * c).

  • a / (b / c) = (a * c) / b.

note

Although these transformations are mathematically equivalent, floating-point arithmetic can introduce slight differences in results due to precision limits. Modern compilers can often apply similar optimizations automatically when explicitly instructed with special compilation flags, such as gcc's and gfortran's -funsafe-math-optimizations.

Code example

C

Have a look at the following code:

// example.c
#include <stdio.h>

__attribute__((const)) float example(float a, float b, float c) {
return a / b / c;
}

int main() {
printf("Result: %0.7f\n", example(1.23, 1.41, 1.89));
return 0;
}

Compiling and running this code produces the following result:

$ gcc --version    
gcc (Debian 12.2.0-14) 12.2.0
$ gcc example.c -o example
$ ./example
Result: 0.4615558

The expression a / b / c can be rewritten with a single division and a multiplication:

// solution.c
...

__attribute__((const)) float example(float a, float b, float c) {
return a / (b * c);
}

...

When compiled and run, this optimized code yields the same result:

$ gcc solution.c -o solution
$ ./solution
Result: 0.4615558

Fortran

Have a look at the following code:

// example.f90
program main
implicit none

print *, "Result:", example(1.23, 1.41, 1.89)

contains

function example(a, b, c)
use iso_fortran_env, only: real32
implicit none

real(kind=real32), intent(in) :: a, b, c
real(kind=real32) :: example

example = a / b / c
end function example

end program main

Compiling and running this code produces the following result:

$ gfortran --version    
GNU Fortran (Debian 12.2.0-14) 12.2.0
$ gfortran example.c -o example
$ ./example
Result: 0.461555779

The expression a / b / c can be rewritten with a single division and a multiplication:

// solution.f90

...

example = a / (b * c)
end function example

...

When compiled and run, the result remains very close to the original, with negligible differences due to the precision limitations of floating-point arithmetic:

$ gfortran solution.c -o solution
$ ./solution
Result: 0.461555809

References