How to round CGFloat
Solution 1
There are already standard functions with behaviors you might need in <math.h>
such as: floorf
, ceilf
,
roundf
, rintf
and nearbyintf
(lasf 'f' means "float" version, versions without it are "double" versions).
It is better to use standard methods not only because they are standard, but because they work better in edge cases.
2013 Update (jessedc)
iOS is no longer only 32 bit. There are a number of other answers to this question that are now more relevant.
Most answers mention importing tgmath.h
Solution 2
2018 Answer
The other answers here are either dated or don't give good examples. It is easy to round a CGFloat
using Swift's built in rounded
function.
let x: CGFloat = 3.5
let y = x.rounded() // 4.0
If you want to round the value in place you can use round
:
var x: CGFloat = 3.5
x.round() // 4.0
Rounding Rules
If you want more precise control over how numbers are rounded, you can use a FloatingPointRoundingRule
.
Away from zero
x.rounded(.awayFromZero)
Numbers above zero are rounded up and numbers below zero are rounded down.
3.000 -> 3.0
3.001 -> 4.0
3.499 -> 4.0
3.500 -> 4.0
3.999 -> 4.0
-3.000 -> -3.0
-3.001 -> -4.0
-3.499 -> -4.0
-3.500 -> -4.0
-3.999 -> -4.0
Down
x.rounded(.down)
Rounds any number with a decimal value down to the next smaller whole number. This is the same as floor(x)
.
3.000 -> 3.0
3.001 -> 3.0
3.499 -> 3.0
3.500 -> 3.0
3.999 -> 3.0
-3.000 -> -3.0
-3.001 -> -4.0
-3.499 -> -4.0
-3.500 -> -4.0
-3.999 -> -4.0
To nearest or away from zero
x.rounded(.toNearestOrAwayFromZero) // same as x.rounded()
Decimal numbers get rounded to the nearest integer value. However, when the value is exactly in the middle (like 3.5
or -3.5
) then positive numbers get rounded up and negative numbers get rounded down.
It may have a long complicated name, but this is normally how one learns rounding in school. It is also the rule used if you just do x.rounded()
.
3.000 -> 3.0
3.001 -> 3.0
3.499 -> 3.0
3.500 -> 4.0 ***
3.999 -> 4.0
-3.000 -> -3.0
-3.001 -> -3.0
-3.499 -> -3.0
-3.500 -> -4.0 ***
-3.999 -> -4.0
To nearest or even
x.rounded(.toNearestOrEven)
This is similar to toNearestOrAwayFromZero
, except now the .5
values get rounded to the even whole number.
3.000 -> 3.0
3.001 -> 3.0
3.499 -> 3.0
3.500 -> 4.0 ***
3.999 -> 4.0
4.500 -> 4.0 ***
-3.000 -> -3.0
-3.001 -> -3.0
-3.499 -> -3.0
-3.500 -> -4.0 ***
-3.999 -> -4.0
-4.500 -> -4.0 ***
Toward zero
x.rounded(.towardZero)
This just has the effect of cutting off any decimal values. If you needed an Int
you could do the same thing with Int(x)
.
3.000 -> 3.0
3.001 -> 3.0
3.499 -> 3.0
3.500 -> 3.0
3.999 -> 3.0
-3.000 -> -3.0
-3.001 -> -3.0
-3.499 -> -3.0
-3.500 -> -3.0
-3.999 -> -3.0
Up
x.rounded(.up)
This is the opposite of .down
. All decimal numbers are rounded up. This is the same as ceil(x)
.
3.000 -> 3.0
3.001 -> 4.0
3.499 -> 4.0
3.500 -> 4.0
3.999 -> 4.0
-3.000 -> -3.0
-3.001 -> -3.0
-3.499 -> -3.0
-3.500 -> -3.0
-3.999 -> -3.0
Notes
- Don't forget to take negative values into account.
- The results of
round
androunded
are stillCGFloat
. If you need anInt
you have to convert it likeInt(myCGFloat)
. - There is no need to use the C math functions
round(x)
,ceil(x)
andfloor(x)
anymore. However, if you do use them, they handle both 64 and 32 bit architecture so any answers you may have seen withroundf
,ceilf
andfloorf
are now obsolete.
Solution 3
A CGFloat
is typedef'd to either a double
or a float
, so you can round them like any other real type:
CGFloat round(CGFloat aFloat)
{
return (int)(aFloat + 0.5);
}
Note that while this works with floats small enough to carry a fraction, it may act weird on large values.
Solution 4
You are reinventing the wheel - and this is a C question, not Objective C. Just use the standard C round() function.
Solution 5
Try #import "tgmath.h"
.
The <tgmath.h>
header will include the headers <math.h>
and <complex.h>
and will define several type-generic macros.
Johannes Jensen
My name's Johannes, and I think this is a great site for asking questions about programming subjects you are insecure about :)
Updated on May 08, 2020Comments
-
Johannes Jensen almost 4 years
I made this method
+ (CGFloat) round: (CGFloat)f { int a = f; CGFloat b = a; return b; }
It works as expected but it only rounds down. And if it's a negative number it still rounds down.
This was just a quick method I made, it isn't very important that it rounds correctly, I just made it to round the camera's x and y values for my game.
Is this method okay? Is it fast? Or is there a better solution?
-
Johannes Jensen about 14 yearsAh, thank you, Assuming the iPhone is 32-bit it'd be best to use those float functions. :D
-
Paul Lynch almost 11 yearsI am curious why this got two downvotes on the same day - especially as it is an exactly correct answer, just not as expansive as the accepted one.
-
Clafou over 10 yearsAnyone knows a macro to allow coding for 32-bit and 64-bit CPUs?
-
hfossli over 10 yearsWell
round()
is fordoubles
androundf()
is forfloats
.CGFloat
is on 32-bit systems afloat
and on 64-bit systems adouble
-
Paul Lynch over 10 yearsStill doesn't explain the down votes - remember that this was three years ago!
-
hfossli over 10 yearsMight be due to the theoretical possibility of a CGFloat being redefined to double
-
Saren Inden over 9 yearsJust create your own macro, see my comment somewhere else in this page
-
Matt Gibson over 9 yearsI wouldn't re-invent the wheel here. tgmath.h ("type generic" math), as mentioned in other answers, already provides good macros for dealing with architecturally-different types.
-
Saren Inden over 9 yearsThis is just an example that can be applied for multiple solutions. Perhaps you do not agree on this example but can you tell me how NSUserDefaults i.e. can store an CGFloat? It has functions to set an float or double. Just like NSNumber does not have an function to retrieve an CGFloat. There are a lot of ways that this might be useful. And of course i do agree that you should not reinvent the wheel.
-
zeroimpl over 9 yearstgmath is overkill when all most people need is the right variant of round/floor/ceil. I also don't like that it redefines the standard functions, rather then using new names. I prefer this simple macro approach.
-
Dakine83 almost 7 yearsGreat example of a great answer on SO. Thank you.
-
gog over 5 yearsThis would be a great answer, except for the fact that the question is tagged
objective-c
...