How to use println in Swift to format number
Here's the shortest solution I found thus far:
let avgTemp = 66.844322156
println(NSString(format:"%.2f", avgTemp))
Its like the swift version of NSString's stringWithFormat
Precision String Format Specifier In Swift
My best solution so far, following from David's response:
import Foundation
extension Int {
func format(f: String) -> String {
return String(format: "%\(f)d", self)
}
}
extension Double {
func format(f: String) -> String {
return String(format: "%\(f)f", self)
}
}
let someInt = 4, someIntFormat = "03"
println("The integer number \(someInt) formatted with \"\(someIntFormat)\" looks like \(someInt.format(someIntFormat))")
// The integer number 4 formatted with "03" looks like 004
let someDouble = 3.14159265359, someDoubleFormat = ".3"
println("The floating point number \(someDouble) formatted with \"\(someDoubleFormat)\" looks like \(someDouble.format(someDoubleFormat))")
// The floating point number 3.14159265359 formatted with ".3" looks like 3.142
I think this is the most Swift-like solution, tying the formatting operations directly to the data type. It may well be that there is a built-in library of formatting operations somewhere, or maybe it will be released soon. Keep in mind that the language is still in beta.
Swift number formatting
You can construct a string with a c-like formatting using this constructor:
String(format: String, arguments:[CVarArgType])
Sample usage:
var x = 10
println(String(format: "%04d", arguments: [x])) // This will print "0010"
If you're going to use it a lot, and want a more compact form, you can implement an extension like this:
extension String {
func format(arguments: [CVarArgType]) -> String {
return String(format: self, arguments: arguments)
}
}
allowing to simplify its usage as in this example:
"%d apples cost $%03.2f".format([4, 4 * 0.33])
String formatting of a Double
There's no way to do this using String
interpolation.
You can find a good discussion about this on this Apple Dev Forum post.
You can use NSNumberFormatter
or NSDateFormatter
to format the output.
Alternatively, to use printf
-like syntax, you can still use NSString
:
var str = NSString(format: "Hello, world %.2f", 42.12312312313)
Format println output in a table
I found a quick and easy way to generate columnar text output in Swift (3.0) using the String method "padding(::)" [In Swift 2.x, the method is named "stringByPaddingToLength(::)"]. It allows you to specify the width of your column, the text you want to use as a pad, and the index of the pad to start with. Works like a charm if you don't mind that it only works with left-aligned text columns. If you want other alignments, you have to buy into the other methods of character counting and other such complexities.
The solution below is contrived to illustrate the utility of the method "padding(::)". Obviously, the best way to leverage this would be to create a function that iterated through a collection to produce the desired table while minimizing code repetition. I did it this way to focus on the task at hand.
Lastly, "println" doesn't seem to exist in Swift 2.x+, so I reverted to "print()".
To illustrate an example using your stated problem:
//Set up the data
let n : Int = 5
let result1 = 1000.0
let result2 = 20000.0
let time1 = "1000ms"
let time2 = "1250ms"
//Establish column widths
let column1PadLength = 8
let columnDefaultPadLength = 12
//Define the header string
let headerString = "n".padding(toLength: column1PadLength, withPad: " ", startingAt: 0) + "result1".padding(toLength: columnDefaultPadLength, withPad: " ", startingAt: 0) + "result2".padding(toLength: columnDefaultPadLength, withPad: " ", startingAt: 0) + "time1".padding(toLength: columnDefaultPadLength, withPad: " ", startingAt: 0) + "time2".padding(toLength: columnDefaultPadLength, withPad: " ", startingAt: 0)
//Define the line separator
let lineString = "".padding(toLength: headerString.characters.count, withPad: "-", startingAt: 0)
//Define the string to display a line of our data
let nString = String(n)
let result1String = String(result1)
let result2String = String(result2)
let dataString = nString.padding(toLength: column1PadLength, withPad: " ", startingAt: 0) + result1String.padding(toLength: columnDefaultPadLength, withPad: " ", startingAt: 0) + result2String.padding(toLength: columnDefaultPadLength, withPad: " ", startingAt: 0) + time1.padding(toLength: columnDefaultPadLength, withPad: " ", startingAt: 0) + time2.padding(toLength: columnDefaultPadLength, withPad: " ", startingAt: 0)
//Print out the data table
print("\(headerString)\n\(lineString)\n\(dataString)")
The output will be printed to your console in a tidy columnar format:
n result1 result2 time1 time2
--------------------------------------------------------
5 1000.0 20000.0 1000ms 1250ms
Changing the variable "columnDefaultPadLength" from 12 to 8 will result in the following output:
n result1 result2 time1 time2
----------------------------------------
5 1000.0 20000.0 1000ms 1250ms
Finally, reducing the padding length to a value less than the data truncates the data instead of generating errors, very handy! Changing the "columnDefaultPadLength" from 8 to 4 results in this output:
n resuresutimetime
------------------------
5 1000200010001250
Obviously not a desired format, but with the simple adjustment of the padding length, you can quickly tweak the table into a compact yet readable form.
How to print formatted Decimal value in Swift?
Decimal
is bridged with NSDecimalNumber
, which is a subclass of NSNumber
so NSNumberFormatter
can handle it
let decimal = Decimal(11.24)
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
let string = formatter.string(from: decimal as NSDecimalNumber)!
Swift Print function formatting
Yes, it is similar to ${} in javaScript, and it is called String Interpolation:
String interpolation is a way to construct a new String value from a mix of constants, variables, literals, and expressions by including their values inside a string literal.
You can find more detailed information in here: Swift Documentation
under the section "String Interpolation".
Swift 4: Formatting number's into friendly K's
This answer formats by truncating (versus rounding). 1,515
rounded would generate 2k
whereas truncated would generate 1.5k
. The function requires reducing a number's scale (removing digits to the right of the decimal) which I've just packaged as an extension so it can be used anywhere (not just in the function).
extension Double {
func reduceScale(to places: Int) -> Double {
let multiplier = pow(10, Double(places))
let newDecimal = multiplier * self // move the decimal right
let truncated = Double(Int(newDecimal)) // drop the fraction
let originalDecimal = truncated / multiplier // move the decimal back
return originalDecimal
}
}
func formatNumber(_ n: Int) -> String {
let num = abs(Double(n))
let sign = (n < 0) ? "-" : ""
switch num {
case 1_000_000_000...:
var formatted = num / 1_000_000_000
formatted = formatted.reduceScale(to: 1)
return "\(sign)\(formatted)B"
case 1_000_000...:
var formatted = num / 1_000_000
formatted = formatted.reduceScale(to: 1)
return "\(sign)\(formatted)M"
case 1_000...:
var formatted = num / 1_000
formatted = formatted.reduceScale(to: 1)
return "\(sign)\(formatted)K"
case 0...:
return "\(n)"
default:
return "\(sign)\(n)"
}
}
You can fine tune this method for specific cases, such as returning 100k
instead of 100.5k
or 1M
instead of 1.1M
. This method handles negatives as well.
print(formatNumber(1515)) // 1.5K
print(formatNumber(999999)) // 999.9K
print(formatNumber(1000999)) // 1.0M
Swift: format console-log
First, for the time, you can get the current hour and minute as String:
func printTime()->String{
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute, fromDate: date)
let hour = components.hour
let minutes = components.minute
return "\(hour):\(minutes)"
}
And for the function etc. you can use the Swift Literal Expressions __FILE__
, __FUNCTION__
and __LINE__
.
But you don't want to set it each time you want to log. So you could do something like that:
func prettyPrint(print: String, file:String = __FILE__, functionName: String = __FUNCTION__, line:Int = __LINE__) {
println("\(printTime()) \(file) > \(functionName) [line \(line)] \(print)")
}
You call prettyPrint
like that:
prettyPrint("hey")
And you will get the following output:
/Path/To/Your/File/MyClass.swift > hello [line 81] hey
But as you only want the name of your class, you can remove the path with the following function:
func getFile(path:String = __FILE__)->String{
var parts = path.componentsSeparatedByString("/")
return parts[parts.count-1]
}
Or, as ChikabuZ mentioned in his answer you can directly check the class:
let className = NSStringFromClass(self.classForCoder).pathExtension
Final Function
And here the final function(s):
func getFile(path:String = __FILE__)->String{
var parts = path.componentsSeparatedByString("/")
return parts[parts.count-1]
}
func prettyPrint(print: String, functionName: String = __FUNCTION__, line:Int = __LINE__) {
println("\(printTime()) \(getFile()) > \(functionName) [line \(line)] \(print)")
}
func printTime()->String{
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute, fromDate: date)
let hour = components.hour
let minutes = components.minute
return "\(hour):\(minutes)"
}
And the result will be:
MyClass.swift > hello [line 81] hey
You should also note @emaloney's answer to this question. Specifically that
println()
-based solutions result in output being captured by the Apple System Log (ASL).
Ideally switch to NSLog or a full blown logging system
Related Topics
How to Make Cells Have a Gradient Background
Realitykit - How to Set a Modelentity's Transparency
How to Generate Random Numbers Without Repetition in Swift
Retrieve Multiple Photos Under a Node from Firebase Storage
Making Parts of Text Bold in Swiftui
Why Do Integers Not Conform to the Anyobject Protocol
Add Constraints to Generic Parameters in Extension
Print the Nstableview's Row Number of the Row Clicked by the User
Open a Filedialog in Swiftui on MACos
Incorrect String to Date Conversion Swift 3.0
Perform Segue from Another Class with Helper Function
Swift 3 - Uibutton Adding Settitle from Plist and Database
Get Bogus Value When Execute Break Point in a Variable