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

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    65

    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.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Change 2 to 2.0 and 1 to 1.0.

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by tabstop View Post
    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.

  4. #4
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    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?

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    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.

  6. #6
    Registered User
    Join Date
    Nov 2005
    Posts
    673
    To clearly state your purpose do what tabstop suggested.
    Code:
    double x = double((WIDTH - 2 * MARGIN) / (MAX - 1) * i);

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    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.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    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.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  9. #9
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    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. #10
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Quote Originally Posted by tabstop View Post
    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.

  11. #11
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Really? I did not know that. I would double check that, but I am not in that kind of mood today.

  12. #12
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    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.

  13. #13
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    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.

  14. #14
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by master5001 View Post
    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).
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  15. #15
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by Thantos View Post
    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.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM
  2. Errors that make no sense...
    By applescruff in forum C++ Programming
    Replies: 22
    Last Post: 03-04-2005, 05:44 PM
  3. Trying to make this code faster & Cramer
    By just2peachy in forum C++ Programming
    Replies: 3
    Last Post: 12-03-2004, 10:54 AM
  4. getline problem
    By scottmanc in forum C++ Programming
    Replies: 9
    Last Post: 04-13-2003, 09:27 PM
  5. Hi, could someone help me with arrays?
    By goodn in forum C Programming
    Replies: 20
    Last Post: 10-18-2001, 09:48 AM