3

Given the following:

int a = 10, b = 5, c = 3, d = 1;
int x = 3,  y = 2, z = 2;

return (float) a/x + b/y + c/z + d;

This presumably casts our precision to float and then performs our sequence of divisions at floating point precision.

What is the correct way to update this using C++ style casts?

Should this really be rewritten as:

return static_cast<float>(a) / static_cast<float>(b) + ... ?
Benjamin Trent
  • 7,378
  • 3
  • 31
  • 41
  • 4
    I would do `return double(a)/x + double(b)/y + double(c)/z + d;` –  Jun 19 '14 at 16:32
  • C-style casts for numeric conversions are IMO ok. The problem is when you use it to cast pointers or cast away constness. – T.C. Jun 19 '14 at 16:35
  • Why aren't you using `float` as type of `a,b,c,d,x,y,z`? – milleniumbug Jun 19 '14 at 16:49
  • "This presumably casts our precision to float and then performs our sequence of divisions at floating point precision." Who presumes this? – Joshua Taylor Jun 19 '14 at 17:01
  • Woops -- yeah, this was a typo. I intended to provide (float) casts for each division. I'm going to leave the question as-is however, in case it's useful for others. Thanks! – user3757349 Jun 19 '14 at 17:19

5 Answers5

7

Start by correcting your code:

(float) a/x + b/y + c/z + d

produces 7.33333, while the correct result is 8.33333. Why? because b/y and c/z divisions are done in ints (demo).

The reason the result is incorrect is that division takes precedence over addition: your program needs to divide b by y and c by z before adding them to the result of division of a by x, which is float.

You need to cast one of the division operands to get this to work correctly. C cast works fine, but if you would rather use C++-style cast, here is how you can do it:

return static_cast<float>(a) / b + static_cast<float>(b) / y +
   static_cast<float>(c) / z + d;
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
5

/ has higher precedence than +, so b/y will be performed in int, not in float.

The correct way to perform each division in float is to cast at least one operand to float:

static_cast<float>(a)/x + static_cast<float>(b)/y + static_cast<float>(c)/z + d

This is clearer than the equivalent C expression:

(float) a/x + (float) b/y + (float) c/z + d

Here one requires knowledge of precedence to realise that the cast to float binds tighter than the division.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • 1
    A function-style cast, `float(a)/x`, might be clearer still, in my opinion. The verbose `static_cast`s give a lot of noise for little benefit. – Mike Seymour Jun 19 '14 at 17:00
1
return (float) a/x + b/y + c/z + d; 

is not correct if you want to return the float value of sum of all divisions. In above expression only a/x is float division and rest of them are int division (because of heiger precedence of / operator than +) which will result in value truncation. Better to stick with

return (double)a/x + (double)b/y + (double)c/z + d;    
haccks
  • 104,019
  • 25
  • 176
  • 264
0
int a = 10, b = 5, c = 3, d = 1;
int x = 3,  y = 2, z = 2;

return (float) a/x + b/y + c/z + d;

This presumably casts our precision to float and then performs our sequence of divisions at floating point precision.

No, it casts a to float and so a/x is performed as a floating point divide, but b/y and c/z are integer divides. Afterwards, the sums are computed after converting the integer division results to float.

This is because casts are simply another operator, and they have higher precedence than + and /. Dividing float by an int or adding a float to an int causes the ints to be automatically converted to floats.

If you want floating point division then you need to insert casts so that they are applied prior to the divisions, and then the other values get automatically promoted.

    return (float) a/x + (float) b/y + (float) c/z + d;

Casting using C++ syntax is exactly the same, except the syntax won't let you get confused about what's actually being cast:

return static_cast<float>(a)/x +  static_cast<float>(b)/y +  static_cast<float>(c)/z + d;

You can also use constructor syntax, which also has the benefit of clearly showing what's cast:

return float(a)/x +  float(b)/y +  float(c)/z + d;

Or you can simply use temporary variables:

float af = a, bf = b, cf = c;
return af/x + bf/y +  cf/z + d;
bames53
  • 86,085
  • 15
  • 179
  • 244
-1

The cast is only necessary with division operation. And you can lighten syntax this way:

return 1.0*a/x + 1.0*b/y + 1.0*c/z + d;

This will compute the result as double type, that gets automatically casted to float if the function returns this type.

kebs
  • 6,387
  • 4
  • 41
  • 70
  • 1
    IMO the `1.0*...` makes it less clear what you're trying to do when you could instead cast to float/double. – maxywb Jun 19 '14 at 16:41
  • This may increase the amount of work the compiler does (multiplication probably can't be removed, just as addition with 0.0 doesn't get removed), so this is worse than the cast. – stefan Jun 19 '14 at 16:42
  • @maxywb: That's a matter of point of view, I disagree. But, anyway, the OP has now lots of choices ! – kebs Jun 19 '14 at 16:43
  • @stefan: sorry, could you elaborate, I'm curious. What do you mean by `multiplication probably can't be removed` ? – kebs Jun 19 '14 at 16:44
  • @kebs for `1.0 * a` to be performed, `a` has to be casted to `double`, that's what we want. But the compiler still performs `1.0 * da` where `da` is the "double `a`". Although any mathematician says that this is `da`, compilers may not be able to optimize this away. – stefan Jun 19 '14 at 16:46
  • @stefan: I would seriously be surprised if any modern compiler didn't optimize this! Similar to the `if(1)` statement causes no cast from int to bool, I think that `1.0*(int value)` automatically casts the value to double. Might be worth a benchmark... – kebs Jun 19 '14 at 16:52
  • @kebs true! To me this seems like a better answer for a python related question, but IMO making code more obvious is preferable. This is certainly "easier" to write, but I can certainly see someone complaining about this in a code review as typing the `cast` makes it explicit. – maxywb Jun 19 '14 at 16:53
  • @kebs it may be possible with multiplication by 1.0, but it's certainly not done with addition with 0.0. Just try it. This optimization will be compiler dependent. – stefan Jun 19 '14 at 16:55
  • 1
    @stefan Even in under strict IEEE754 conformance I believe eliminating the multiplication is trivial. [demo](http://coliru.stacked-crooked.com/a/2bb55e3d2b89e82b) – bames53 Jun 19 '14 at 16:57
  • Actually, if the person was writing a function template that accepts any type (think `int`, `double`, `std::complex`, anything from Boost.Units) conversion to double may not be possible, but multiplication by `1.0` would ensure that, when necessary, types are converted to double and then calculated. – SirGuy Jun 19 '14 at 16:58
  • @bames53 relatively irrelevant: People that see this kind of code may think that it works the same with `0.0 + a`, which does not. It's a really bad idea to introduce this instead of clear and optimal casts. – stefan Jun 19 '14 at 17:00
  • @stefan eliminating addition of `0.0` can't be done when adding to an arbitrary `double` because there are special cases for certain `double` values. But eliminating addition of `0.0` can be done when the addition is with an `int` because there are no special cases for any `int` value: [demo](http://coliru.stacked-crooked.com/a/91b2a7e923b1184d) – bames53 Jun 19 '14 at 17:00
  • @bames53 As I've said: also this demo is irrelevant: it's not guaranteed that every compiler will do this. It's a stupid idea to use any of these methods. – stefan Jun 19 '14 at 17:02
  • @stefan Ok, now I see what you mean when talking about addition, I didn't get your point. But I never talked about such a thing, and would never write that, of course. On the bottom line, I **agree** that its better to have explicit casts, this situation is however the single situation where I recommend this. I do mostly scientific software, and people are used to this hack. – kebs Jun 19 '14 at 17:04
  • @bames53 g++-4.9 does _not_ perform the "+0.0" addition operation removal optimization. And that's a pretty major compiler. – stefan Jun 19 '14 at 17:06
  • @stefan well, correctness is guaranteed whether the compiler optimizes this or not. I support readability over performance in general so if someone finds this more readable for their own code then that seems fine to me. – bames53 Jun 19 '14 at 17:08