user3757349
user3757349

Reputation: 51

What is the correct way to use C++ style casts to perform an expression at a desired precision?

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) + ... ?

Upvotes: 3

Views: 481

Answers (5)

bames53
bames53

Reputation: 88215

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;

Upvotes: 0

haccks
haccks

Reputation: 106102

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;    

Upvotes: 1

kebs
kebs

Reputation: 6707

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.

Upvotes: -1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726929

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;

Upvotes: 7

ecatmur
ecatmur

Reputation: 157454

/ 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.

Upvotes: 5

Related Questions