What's the best way to make an expression evaluate as a double?

Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 10-05-2008
jw232
What's the best way to make an expression evaluate as a double?
Code:

`double x = (WIDTH - 2 * MARGIN) / (MAX - 1) * i;`
If I wanted to make the above statement evaluate as a double for the most accuracy where the variables are ints, what's the best way to do that? I would put (double) in front of every variable to be safe, but that seems repetitive.
• 10-05-2008
tabstop
Change 2 to 2.0 and 1 to 1.0.
• 10-06-2008
grumpy
Quote:

Originally Posted by tabstop
Change 2 to 2.0 and 1 to 1.0.

Even changing the 1 to 1.0 is optional.

This assumes your notion of "best" means "least additional typing". However, the scope for confusion with such a line is large. A common problem in a team environment is that one person will write such a line, and someone else will come along and remove parts they consider unnecessary. That ".0" will therefore probably be removed by someone and there will then be a small bug in the program that shows up occasionally and is very hard to track down.

It is even more embarrassing when you do that to your own code, and realise that the idiot who removed the ".0" and broke the program is yourself.
• 10-06-2008
C_ntua
If you don't change the 1 to 1.0, is it guaranteed that (MAX - 1) * i won't be evaluated first, as an int?
• 10-06-2008
tabstop
Order of operations: a/b*c = (a/b)*c, not a/(b*c). (They're not equivalent).

And I suppose you could always add a comment why it's 2.0, and not 2; or, if you're paranoid, you can cast the whole expression to double.
• 10-06-2008
Raigne
To clearly state your purpose do what tabstop suggested.
Code:

`double x = double((WIDTH - 2 * MARGIN) / (MAX - 1) * i);`
• 10-06-2008
laserlight
Quote:

To clearly state your purpose do what tabstop suggested.
You still need to make sure that the operations in the expression are performed with doubles by making 2 be 2.0, and of course static_cast should be preferred to a C-style cast.
• 10-06-2008
King Mir
Changing 2 to 2.0 is the minimal solution. For more clarity you would want to cast each of WIDTH, MARGIN, and MAX, and change 1 to 1.0.

Putting the cast around the whole thing is pretty pointless, cause it is clear that you are assigning to a double. Furthermore such a habit could sometimes hide when the expression evaluates to a non-numeric type, and stop a compiler from giving loss of precision warnings. Using a static cast helps but does not eliminate this potential for error.
• 10-06-2008
master5001
You need only change one operand to a double, King. If an integer interacts with a double in any way it gets promoted to a double.
• 10-06-2008
Thantos
Quote:

Originally Posted by tabstop
Order of operations: a/b*c = (a/b)*c, not a/(b*c). (They're not equivalent).

And I suppose you could always add a comment why it's 2.0, and not 2; or, if you're paranoid, you can cast the whole expression to double.

IIRC order of operations isn't the same as order of evaluation. The compiler is free to evaluate the parts in any order it chooses.
• 10-06-2008
master5001
Really? I did not know that. I would double check that, but I am not in that kind of mood today.
• 10-06-2008
Thantos
I should clarify a bit: Any order that still follows the rules of the order of operations.

So if the case of:
Code:

`(WIDTH - 2 * MARGIN) / (MAX - 1) * i;`
It could evaluate (MAX - 1) before evaluating (WIDTH - 2 * MARGIN). It could even evaluate (WIDTH - 2 * MARGIN) * i before dividing by (MAX - 1) but I kinda doubt it would.
• 10-06-2008
master5001
Ah ok. Yeah I feel ya on that one. In all the time I have been posting on the forums (which has been a while) I have never found that you were in much need of correction, Thantos. Thats why I just figured I wasn't tracking what you meant well. I have been up since 5:00 this morning. So I am too tired to know what is what.
• 10-06-2008
King Mir
Quote:

Originally Posted by master5001
You need only change one operand to a double, King. If an integer interacts with a double in any way it gets promoted to a double.

That's why the minimal solution is to convert the 2. Alternatively you could cast MARGIN. Anything else and the result may be different. That's why the safest approach is to cast everything, and write everything in terms of doubles. Then there is less room for error.

For example, casting WIDTH is not sufficient if MARGIN*2 will overflow an int (or whatever larger size MARGIN is).
• 10-06-2008
King Mir
Quote:

Originally Posted by Thantos
It could evaluate (MAX - 1) before evaluating (WIDTH - 2 * MARGIN). It could even evaluate (WIDTH - 2 * MARGIN) * i before dividing by (MAX - 1) but I kinda doubt it would.

Yes to the first, no to the second. / and * have the same precedence and are evaluated left to right. The rule is such that it never matters for primitives, only for impure functions and state changing classes.
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last