1

I've been studying c++, and I ran into an implicit conversion issue that I don't understand. In this code:

#include <iostream>
using namespace std;
int main(){
    int i;
    i = 1 / 2 * 2 / 1. * 2. / 4 * 4;
    cout << i << endl;

    i = 3.5 + 2 + 1.6;
    cout << i << endl;

    i = 2 + 3.5 + 1.6;
    cout << i << endl;

    return 0;
}

Ithe outputs are: 0, 7 and 7 respectively.

In the last 2 examples, the compiler is implicitly converting the elements to doubles, so the sum = 7.1, which is then cast to an int to get 7.

Because the 1st example also has doubles, I'd expect all of those elements to be converted to doubles as well, and the sum being 2.0, before being cast to 2, but the result is 0, so it seems the "1/2" is being treated as ints, giving a result of 0. I'm not sure that's what the compiler is doing, but that's what it seems like.

I thought if any element was a double, the compiler would implicitly convert all elements to double. This doesn't happen in the 1st case though. Can someone please explain why the compiler converts these differently? Thanks.

Claudio Cortese
  • 1,372
  • 2
  • 10
  • 21
Gaylord
  • 21
  • 4
  • 2
    It is done "2 by 2". – Jarod42 Feb 21 '18 at 21:47
  • All meaningful division is by `2` in example 1 so integer division applies. – David C. Rankin Feb 21 '18 at 21:48
  • 1
    "I thought if any element was a double, the compiler would implicitly convert all elements to double. " - you thought wrong `2/3 + 0.1` performs integer arithmetic on the first subexpression. –  Feb 21 '18 at 21:49
  • The type casting is applied when it encounters the floating point number. So, in the first case, `1/2` would still be an `int` and would evaluate to 0. The type casting will occur at `1.`. – Aditya Feb 21 '18 at 21:49
  • 1
    A rule of thumb: if you need `double` results - use type `double`. C++ can't be learned by guessing. Please have a look at this [C++ books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) list. – Ron Feb 21 '18 at 21:52
  • 1
    "I thought ..." - well, *don't*. Don't think you know something or guess; *know* you know - by looking it up and being 100% sure. Don't assume things, only know. – Jesper Juhl Feb 21 '18 at 21:54
  • *I thought if any element was a double, the compiler would implicitly convert all elements to double.* -- I have to ask, are you coming from using another computer language? If so, this is where you will get burned very badly if you're leveraging what you know about other computer languages when learning C++. – PaulMcKenzie Feb 21 '18 at 22:06
  • 1
    @Aditya — there are no type casts in this code. There are implicit conversations. A type cast is something you write in your code to tell the compiler to do a conversion. – Pete Becker Feb 21 '18 at 23:07
  • @PeteBecker Thought someone would mention that. I used the term because the question involved its usage. Wanted to convey the information so he could understand it. I realized I should've addressed that as well later but I was past 5 minutes by that time. Didn't want to clutter the comments by adding another one. I see I should have added the extra comment now. – Aditya Feb 22 '18 at 14:52
  • 1
    @Jesper, I'm asking so I know. I'm doing this analysis so I know. Every "knowing" begins with thought. I'm learning by doing, and going to the community to get clarification on the details. I thought that's what stackoverflow was for. – Gaylord Feb 23 '18 at 20:25
  • @Gaylord I support your approach. Mentioning your thought does help in understanding where and why you are not understanding the problem, thus making the answer to be clear. However, I think Jesper just worded his statement a bit crudely - his emphasis should have been to ask you to work independently to approach the right answer. I do think you've at least tried it - otherwise you wouldn't have had the initial thought to begin with. Cheers – Aditya Feb 26 '18 at 22:15

2 Answers2

9

I thought if any element was a double, the compiler would implicitly convert all elements to double. This doesn't happen in the 1st case though.

No. Compiler parse an expression step by step, not as a whole. For

i = 1 / 2 * 2 / 1. * 2. / 4 * 4;

it is parsed as i = ((1 / 2) * 2).... In the first parenthesis, there are only int, so int arithmetics is applied, which leads a 0. This 0 makes the whole expression 0.

llllllllll
  • 16,169
  • 4
  • 31
  • 54
4

As stated in C++ operator precedence and associativity * (multiply) and / (division) has the same precedence and left to right associativity. So they parsed from left to right and result type of every operation determined one by one according to rules - pay attention to Integral promotion section there (note that evaluation order is different thing and not directly related), not whole expression is promoted to double if you have one of that type there. So logically this code:

i = 1 / 2 * 2 / 1. * 2. / 4 * 4;

is equal to this:

auto a = 1 / 2; // a - int
auto b = a * 2; // b - int
auto c = b / 1.; // c - double
auto d = c * 2.; // d - double
auto e = d / 2;  // e - double
auto f = e * 4;  // f - double
i = f;

and type of every variable a-f is determined separately.

Slava
  • 43,454
  • 1
  • 47
  • 90