4

I was writing a function to calculate the volume of a sphere when I encounter a problem and I don't know why if I change 4/3 * PI to PI * 4/3 I got different result. What is the order of evaluation, if I use parenthesis like (4/3) * PI and PI * (4/3) I got the wrong answer in both cases.

#define PI 3.141592

float Volume(int radius){
      return (4/3 * PI * pow(radius, 3));
}

float Volume(int radius){
      return (PI * 4/3 * pow(radius, 3)); //the good one
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    When you divide two integers you get an integer with the truncated quotient. – eesiraed Apr 28 '20 at 22:43
  • 1
    https://stackoverflow.com/questions/7571326/why-does-dividing-two-int-not-yield-the-right-value-when-assigned-to-double – MPops Apr 28 '20 at 22:43

2 Answers2

6

According to the C++ Standard (5.6 Multiplicative operators)

1 The multiplicative operators *, /, and % group left-to-right.

Thus this expression

4/3 * PI 

is evaluated like

( 4/3 ) * PI 

So in this sub-expression 4 / 3 there is used the integer arithmetic and result is equal to 1.

This expression

PI * 4/3

also is evaluated from left to right like

( PI * 4 )/3

but in this case there is used the float arithmetic. The operand 4 is converted to the type of the variable PI that has the type double due to the usual arithmetic conversions. Then in turn the operand 3 is also converted to the type double because its left operand (expression) ( PI * 4 )has the type double.

In this expression

PI * (4/3)

again inside the parentheses there is used the integer arithmetic and the result of the sub-expression is 1.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

To get the correct result, force the answer to be floating point like such:

return 4.0/3 * PI * pow(radius, 3);

Also, the * and / operators have the same precedence, so the expression will evaluate from left to right. So putting parentheses around 4/3 was right, except it does integer division.

Alexander Wu
  • 433
  • 4
  • 8
  • It is better to use to use floating point literals across the board if that's what you want: `return (4.0/3. * PI * pow(radius, 3.));`. Most modern compilers will figure it out but it's more sensible and clearer not to rely on it. – Jack Aidley Apr 28 '20 at 22:49
  • Interesting, I've never heard that before. I've mostly seen people make the first number floating point, so that the whole expression will be. – Alexander Wu Apr 28 '20 at 22:57