I\'m printing out a number whose value I don\'t know. In most cases the number is whole or has a trailing .5. In some cases the number ends in .25 or .75, and very rarely th
My 2 cents ;) Swift 3 ready
Rounds the floating number and strips the trailing zeros to the required minimum/maximum fraction digits.
extension Double {
func toString(minimumFractionDigits: Int = 0, maximumFractionDigits: Int = 2) -> String {
let formatter = NumberFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.minimumFractionDigits = minimumFractionDigits
formatter.maximumFractionDigits = maximumFractionDigits
return formatter.string(from: self as NSNumber)!
}
}
Usage:
Double(394.239).toString() // Output: 394.24
Double(394.239).toString(maximumFractionDigits: 1) // Output: 394.2
A Float
uses a binary (IEEE 754) representation and cannot represent
all decimal fractions precisely. For example,
let x : Float = 123.456
stores in x
the bytes 42f6e979
, which is approximately
123.45600128173828
. So does x
have 3 or 14 fractional digits?
You can use NSNumberFormatter
if you specify a maximum number
of decimal digits that should be presented:
let fmt = NSNumberFormatter()
fmt.locale = NSLocale(localeIdentifier: "en_US_POSIX")
fmt.maximumFractionDigits = 3
fmt.minimumFractionDigits = 0
println(fmt.stringFromNumber(123)!) // 123
println(fmt.stringFromNumber(123.4)!) // 123.4
println(fmt.stringFromNumber(123.45)!) // 123.45
println(fmt.stringFromNumber(123.456)!) // 123.456
println(fmt.stringFromNumber(123.4567)!) // 123.457
Swift 3/4 update:
let fmt = NumberFormatter()
fmt.locale = Locale(identifier: "en_US_POSIX")
fmt.maximumFractionDigits = 3
fmt.minimumFractionDigits = 0
print(fmt.string(for: 123.456)!) // 123.456
You can use %g
to suppress trailing zeros. Then I think you do not need to go through the business of determining the number of places. Eg -
var num1:Double = 5.5
var x = String(format: "%g", num1) // "5.5"
var num2:Double = 5.75
var x = String(format: "%g", num2) // "5.75"
Or this variation where the number of places is specified. Eg -
var num3:Double = 5.123456789
var x = String(format: "%.5g", num3) // "5.1235"
If you want to print a floating point number to 3 decimal places, you can use String(format: "%.3f")
. This will round, so 0.10000001
becomes 0.100
, 0.1009
becomes 0.101
etc.
But it sounds like you don’t want the trailing zeros, so you might want to trim them off. (is there a way to do this with format
? edit: yes, g
as @simons points out)
Finally, this really shouldn’t be a class function since it’s operating on primitive types. Better to either make it a free function, or perhaps extend Double
/Float
:
extension Double {
func toString(#decimalPlaces: Int)->String {
return String(format: "%.\(decimalPlaces)g", self)
}
}
let number = -0.3009
number.toString(decimalPlaces: 3) // -0.301