Formatting decimal places with unknown number

I am printing out a number whose value I do not know. In most cases, the number is an integer or has a trailing .5. In some cases, the number ends in 0.25 or 0.75, and very rarely the number goes to the thousandth place. How to specifically determine this last case? Right now, my code detects an integer (0 decimal places), exactly 0.5 (1 decimal), and then returns to 2 decimal spots in all other scenarios, but I need to go to 3 when it requires it.

class func getFormattedNumber(number: Float) -> NSString { var formattedNumber = NSString() // Use the absolute value so it works even if number is negative if (abs(number % 2) == 0) || (abs(number % 2) == 1) { // Whole number, even or odd formattedNumber = NSString(format: "%.0f", number) } else if (abs(number % 2) == 0.5) || (abs(number % 2) == 1.5) { formattedNumber = NSString(format: "%.1f", number) } else { formattedNumber = NSString(format: "%.2f", number) } return formattedNumber } 
+4
logic swift
source share
4 answers

A Float uses a binary (IEEE 754) representation and cannot represent all decimals exactly. For example,

 let x : Float = 123.456 

stores in x bytes 42f6e979 , which is approximately 123.45600128173828 . So x has 3 or 14 fractional digits?

You can use NSNumberFormatter if you specify the maximum number of decimal digits to be represented:

 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 
+9
source share

My 2 cents;) Swift 3 is ready

Sets a floating-point number and splits trailing zeros into the required minimum / maximum 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)! } } 

Using:

 Double(394.239).toString() // Output: 394.24 Double(394.239).toString(maximumFractionDigits: 1) // Output: 394.2 
+2
source share

You can use %g to suppress trailing zeros. Then I think that you do not need to deal with determining the number of places. For example -

 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 is it a change that indicates the number of seats. For example -

 var num3:Double = 5.123456789 var x = String(format: "%.5g", num3) // "5.1235" 
+1
source share

If you want to print a floating point number up to three decimal places, you can use String(format: "%.3f") . This will be rounded, so 0.10000001 will become 0.100 , 0.1009 will become 0.101 , etc.

But it sounds like you don't want trailing zeros, so you can trim them. (is there a way to do this with format ? edit: yes, g as @simons points out)

Finally, this really should not be a class function, since it works on primitive types. It’s better to either make it a free function or expand 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 
0
source share

All Articles