Update (December 19, 2016): The code in this article was updated for Swift 3.0.
The 1960s Star Trek TV series wasn’t written by engineers, scientists, or mathematicians, which is why one of their tricks for showing you that Mr. Spock was an intellectual badass was having make calculations to a ridiculous degree of preciseness, a dramatic device that TV Tropes calls ludicrous precision.
You don’t want your apps to be as annoying as Spock could sometimes be, which is why rounding is an important operation.
Rounding is useful for things like:
 The limits of your input precision. Suppose you’re calculating the average of the daily high temperatures over the past week, each of which is accurate to the nearest degree. Because of the way an average (or more technically, the mean) is calculated, the result may contain a decimal point. However, the result you report shouldn’t be more precise than the data it’s based on, so you’ll want to round it to the nearest degree.
 The limits of usefulness. If you’re displaying directions for a short trip, you probably wouldn’t want to report the total distance with more than a 1/4 mile or 1/2 kilometer precision, and you’d probably want to state the trip time rounded to the nearest minute. On the other hand, for a trip covering the width of the United States or Canada, anything more precise than rounding the total distance to the nearest 10 miles and the trip time to the nearest halfhour isn’t generally helpful.
 Practical considerations. When performing financial calculations, especially when dealing with cash, you’ll want to round your result to the nearest penny. In countries like Canada, where they’ve phased out the penny, you’ll want to round cash calculations to the nearest nickel.
Swift’s builtin rounding functions
Swift comes builtin with most of the rounding functions in C’s math library. The ones you’re most likely to use are round
, floor
, and ceil
:
round(_:) 
Given a number n, this returns n rounded to the nearest whole number. For example:
With negative numbers, a fractional value of 0.5 or higher rounds the number down, and lower fractional values round the number up:

floor(_:) 
Given a number n, this returns n rounded down to the nearest whole number. For example:

ceil(_:) 
Given a number n, this returns n rounded up to the nearest whole number (you’ve probably guessed that ceil is short for ceiling). For example:

round
, floor
, and ceil
each come in two versions:
 A version that accepts a
Double
argument and returns aDouble
result (Double
s are 64bit numbers and have a precision of at least 15 decimal digits), and  a version that accepts a
Float
argument and returns aFloat
result (Float
s are 32bit numbers and have a precision of as little as 6 decimal digits).
Rounding n to the nearest multiple of x
round
, floor
, and ceil
work well when you’re trying to round to nearest whole number, but they’re not as useful if you’re facing one of these rounding scenarios:
 Rounding a number to the nearest 10 (as demonstrated in the “Rounding Coaster” shown above), 100, 1000, etc.
 Rounding a number to the nearest .1, .01, .001, etc.
 Rounding a dollar value to the nearest penny
 In Canada, which has eliminated the penny (because it costs more than a penny to manufacture one), you calculate change by rounding to the nearest nickel
 Rounding a number to the nearest multiple of x
For situations like the ones listed above, you’ll find these Swift functions handy:
// Given a value to round and a factor to round to, // round the value to the nearest multiple of that factor. func round(_ value: Double, toNearest: Double) > Double { return round(value / toNearest) * toNearest } // Given a value to round and a factor to round to, // round the value DOWN to the largest previous multiple // of that factor. func roundDown(_ value: Double, toNearest: Double) > Double { return floor(value / toNearest) * toNearest } // Given a value to round and a factor to round to, // round the value DOWN to the largest previous multiple // of that factor. func roundUp(_ value: Double, toNearest: Double) > Double { return ceil(value / toNearest) * toNearest }
Here’s the round(_:toNearest:)
function in action:
round(52.376, toNearest: 0.01) // 52.38 round(52.376, toNearest: 0.1) // 52.4 round(52.376, toNearest: 0.25) // 52.5 round(52.376, toNearest: 0.5) // 52.5 round(52.376, toNearest: 1) // 52 round(52.376, toNearest: 10) // 50 round(52.376, toNearest: 100) // 100 round(52.376, toNearest: 1000) // 0
Here’s the roundDown(_:toNearest:)
function in action:
roundDown(52.376, toNearest: 0.01) // 52.37 roundDown(52.376, toNearest: 0.1) // 52.3 roundDown(52.376, toNearest: 0.25) // 52.25 roundDown(52.376, toNearest: 0.5) // 52 roundDown(52.376, toNearest: 1) // 52 roundDown(52.376, toNearest: 10) // 50 roundDown(52.376, toNearest: 100) // 0 roundDown(52.376, toNearest: 1000) // 0
Here’s the roundUp(_:toNearest:)
function in action:
roundUp(52.376, toNearest: 0.01) // 52.38 roundUp(52.376, toNearest: 0.1) // 52.4 roundUp(52.376, toNearest: 0.25) // 52.5 roundUp(52.376, toNearest: 0.5) // 52.5 roundUp(52.376, toNearest: 1) // 53 roundUp(52.376, toNearest: 5) // 55 roundUp(52.376, toNearest: 10) // 60 roundUp(52.376, toNearest: 100) // 100 roundUp(52.376, toNearest: 1000) // 1000
Rounding to a specified number of decimal places
If you want to round a value to a specific number of decimal places, try this function:
// Round the given value to a specified number // of decimal places func round(_ value: Double, toDecimalPlaces places: Int) > Double { let divisor = pow(10.0, Double(places)) return round(value * divisor) / divisor }
Here’s roundToPlaces(_:decimalPlaces:)
in action:
round(52.3761, toDecimalPlaces: 3) // 52.376 round(52.3761, toDecimalPlaces: 2) // 52.38 round(52.3761, toDecimalPlaces: 1) // 52.4 round(52.3761, toDecimalPlaces: 0) // 52.0 // If we put a negative number n into decimalPlaces, // roundToPlaces rounds to the nearest multiple of // 10^abs(n): round(52.3761, toDecimalPlaces: 1) // 50.0 (rounding to nearest multiple of 10) round(52.3761, toDecimalPlaces: 2) // 100.0 (rounding to nearest multiple of 100) round(52.3761, toDecimalPlaces: 3) // 0 (rounding to nearest multiple of 1000))
Removing the fractional part of a number
Sometimes, you just want to lop off anything after the decimal point. That’s what trunc
(short for truncate) is for:
trunc(52.376) // 52.0 trunc(52.576) // 52.0 trunc(52.376) // 52.0 trunc(52.576) // 52.0
Displaying rounded values
There are times when you want to store a precise value but display a rounded one. Use the String
class’ init(format:arguments:)
method and C’s format strings for printf
to display numbers as strings representing rounded values. Here it is in action:
// Remember, these are *string* values! String(format: "%.3f", 52.3761) // "52.376" String(format: "%.2f", 52.3761) // "52.38" String(format: "%.1f", 52.3761) // "52.4" String(format: "%.0f", 52.3761) // "52" String(format: "%.0f", 52.5761) // "53"
Happy rounding!
Thanks to John Maynard Keynes for the title of this article!
9 replies on “Better to be roughly right than precisely wrong: Rounding numbers with Swift”
But:
roundUp(52.376, toNearest: 0.1) // 52.40000000000001
On a related point, how can you create a new type that stores dollars and cents as a floating point value with exactly 2 decimal places? If you do that, all this rounding becomes unnecessary.
I’m writing something to store financial values and it should not be possible to store fractions of a cent, so every value should be x.xx with no trailing figures after the .xx
I want this because for a bank account withdrawal, sometimes you need to check if balance is >= amount being withdrawn. Normal float/double values don’t usually work when checking equality.
[…] To learn more about different rounding functions, click here. […]
[…] Better to be roughly right than precisely wrong: Rounding numbers with Swift […]
@CHiPloveNY: This is because not every number can be accurately stored in a floatpoint number. Observe:
(52.4 as Double) // 52.399999999999999
(52.4 as Double).nestUp // 52.400000000000006
@CHiPloveNY: This is because not every number can be accurately stored in a floatpoint number. Observe:
(52.4 as Double) // 52.399999999999999
(52.4 as Double).nextUp // 52.400000000000006
@Dave: Trying to use floatingpoint numbers for financials is the wrong tool for the job. The reason is right in the name— the decimal point is “floating”. What you need is a “fixedpoint decimal number”.
Fortunately, Foundation provides a class for that— Decimal (or in ObjC, NSDecimalNumber). To create a Decimal number, you can use either of these:
let price1 = Decimal(sign: .plus, exponent: 2, significand: 199994) // 1999.94
let price2 = Decimal(string: “1999.94”)! // 1999.94
Compare to:
let price3 = Double(1999.94) // 1999.9400000000001
@Dave: Also, the range of Decimal isn’t infinite, but it should certainly be big enough for any financial numbers you might need to do math on in the forseeable future. The significand is stored as 128bits, so given an exponent of 2 (for cents), that gives you a range of $3.4 Undecillion to +$3.4 Undecillion ($3,402,823,669,209,384,634,633,746,074,317,682,114.55 to 3,402,823,669,209,384,634,633,746,074,317,682,114.55).
Calculated using:
let min = Decimal(_exponent: 2, _length: 8, _isNegative: 1, _isCompact: 0, _reserved: 0, _mantissa: ( UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max ))
let max = Decimal(_exponent: 2, _length: 8, _isNegative: 0, _isCompact: 0, _reserved: 0, _mantissa: ( UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max ))
How to get 1.00 , if I provide 1.001 ?