6

As strange as it may seems, I can't find how to cleanly convert a float to an int.

This technique

int int_value = (int)(float_value + 0.5);

triggers a

warning: use of old-style cast

in gcc.

So, what is the modern-style, simple way to convert a float to an int ? (I accept the loss of precision of course)

Offirmo
  • 18,962
  • 12
  • 76
  • 97
  • 2
    The most modern way is `std::round`. – chris May 15 '13 at 16:49
  • what does `int int_value = float_value + .5f;` do? Hint: 0.5 is a double. – Aki Suihkonen May 15 '13 at 16:51
  • @chris `round` will return a float. You could call `lround` but that returns a long, not an int. Oh, now I see that you're only talking about the rounding part, not the casting to int part. That'll teach me to read the entire question before commenting :-) – Praetorian May 15 '13 at 16:52
  • @Praetorian, Though I believe it is guaranteed to return something that you can truncate to the right number. I honestly forgot `lround` existed. There's a decent chance `long` will be the same size as `int`, too. – chris May 15 '13 at 16:57
  • 1
    as a side note many(expert term :)) floats cant be casted to int because they are out of int range – NoSenseEtAl May 15 '13 at 17:07

3 Answers3

8

As Josh pointed out in the comments, + 0.5 is not very reliable. For extra security you could combine a static_cast with std::round like so:

int int_value = static_cast<int>(std::round(float_value));

For the casting part, see this excellent post for an explanation.

Community
  • 1
  • 1
Victor Sand
  • 2,270
  • 1
  • 14
  • 32
  • 5
    `+ 0.5` is a surprisingly unreliable way to round, due to floating point math issues. See http://blog.frama-c.com/index.php?post/2013/05/02/nearbyintf1. – Josh Kelley May 15 '13 at 16:53
  • The `static_cast` does absolutely nothing here; once you've done `std::round`, you can just forget it (and get undefined behavior if the flow doesn't fit), or you can assign the results to a `float`, and check against `std::numeric_limits::max()` and `std::numeric_limits::min` before doing the assignment. (The `lexical_cast` is a very bad idea, since it doesn't work.) – James Kanze May 15 '13 at 17:12
  • @JamesKanze: Couldn't omitting the cast generate warnings about precision loss? – Victor Sand May 15 '13 at 17:23
  • @VictorSand A compiler can warn about anything it feels like, including in the presence of a cast. In practice, though... an explicit cast is the traditional way of telling the compiler you know what you're doing, and that this isn't an oversight, so yes, I would expect the cast to have an impact on warnings. – James Kanze May 16 '13 at 08:05
1

try:

int int_value = static_cast<int>(float_value + 0.5);

FYI: different casts in C++ gave a very good explanation about those 4 casts introduced in C++.

Community
  • 1
  • 1
taocp
  • 23,276
  • 10
  • 49
  • 62
1

You could also consider

int int_value = boost::lexical_cast<int>(float_value);

lexical_cast has the benefit of working for all primitive types, and stl strings etc. It also means you don't have to do the (float_value + 0.5) stuff.

Mike B
  • 478
  • 2
  • 11
  • This won't work if the intermediate string contains a decimal point though, and that's likely for a float. Or, if the float is huge. Further, for rounding of negative values, you want to subtract 0.5, so rounding isn't that easy anyway. – Ulrich Eckhardt May 15 '13 at 17:01