What is the function that removes trailing zeros from doubles?
var double = 3.0
var double2 = 3.10
println(func(double)) // 3
println(func(double2)) // 3.1
You can do it this way but it will return a string:
var double = 3.0
var double2 = 3.10
func forTrailingZero(temp: Double) -> String {
var tempVar = String(format: "%g", temp)
return tempVar
}
forTrailingZero(double) //3
forTrailingZero(double2) //3.1
In Swift 4 you can do it like that:
extension Double {
func removeZerosFromEnd() -> String {
let formatter = NumberFormatter()
let number = NSNumber(value: self)
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 16 //maximum digits in Double after dot (maximum precision)
return String(formatter.string(from: number) ?? "")
}
}
example of use: print (Double("128834.567891000").removeZerosFromEnd())
result: 128834.567891
You can also count how many decimal digits has your string:
import Foundation
extension Double {
func removeZerosFromEnd() -> String {
let formatter = NumberFormatter()
let number = NSNumber(value: self)
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = (self.components(separatedBy: ".").last)!.count
return String(formatter.string(from: number) ?? "")
}
}
Removing trailing zeros in output
This scenario is good when the default output precision is desired. We test the value for potential trailing zeros, and we use a different output format depending on it.
extension Double {
var stringWithoutZeroFraction: String {
return truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
}
}
(works also with extension Float, but not Float80)
Output:
1.0 → "1"
0.1 → "0.1"
0.01 → "0.01"
0.001 → "0.001"
0.0001 → "0.0001"
Formatting with maximum fraction digits, without trailing zeros
This scenario is good when a custom output precision is desired.
This solution seems roughly as fast as NumberFormatter + NSNumber solution from MirekE, but one benefit could be that we're avoiding NSObject here.
extension Double {
func string(maximumFractionDigits: Int = 2) -> String {
let s = String(format: "%.\(maximumFractionDigits)f", self)
for i in stride(from: 0, to: -maximumFractionDigits, by: -1) {
if s[s.index(s.endIndex, offsetBy: i - 1)] != "0" {
return String(s[..<s.index(s.endIndex, offsetBy: i)])
}
}
return String(s[..<s.index(s.endIndex, offsetBy: -maximumFractionDigits - 1)])
}
}
(works also with extension Float, but not Float80)
Output for maximumFractionDigits: 2:
1.0 → "1"
0.12 → "0.12"
0.012 → "0.01"
0.0012 → "0"
0.00012 → "0"
Note that it performs a rounding (same as MirekE solution):
0.9950000 → "0.99"
0.9950001 → "1"
In case you're looking how to remove trailing zeros from a string:
string.replacingOccurrences(of: "^([\d,]+)$|^([\d,]+)\.0*$|^([\d,]+\.[0-9]*?)0*$", with: "$1$2$3", options: .regularExpression)
This will transform strings like "0.123000000" into "0.123"
All the answers i found was good but all of them had some problems like producing decimal numbers without the 0 in the beginning ( like .123 instead of 0.123). but these two will do the job with no problem :
extension Double {
func formatNumberWithFixedFraction(maximumFraction: Int = 8) -> String {
let stringFloatNumber = String(format: "%.\(maximumFraction)f", self)
return stringFloatNumber
}
func formatNumber(maximumFraction: Int = 8) -> String {
let formatter = NumberFormatter()
let number = NSNumber(value: self)
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = maximumFraction
formatter.numberStyle = .decimal
formatter.allowsFloats = true
let formattedNumber = formatter.string(from: number).unwrap
return formattedNumber
}
}
The first one converts 71238.12 with maxFraction of 8 to: 71238.12000000
but the second one with maxFraction of 8 converts it to: 71238.12
This one works for me, returning it as a String for a text label
func ridZero(result: Double) -> String {
let value = String(format: "%g", result)
return value
}
Following results
ridZero(result: 3.0) // "3"
ridZero(result: 3.5) // "3.5"
Related
I have a question about number formatter.
I want to add thousand separator mark to my double number.
And I also to set it's minimumFractionDigits, but I failed.
func formatterNumberToString(_ numberText: String, digits: Int) -> String {
let str = numberText
let formatter = Formatter.withSeparator
formatter.minimumFractionDigits = digits
let finalStr = formatter.string(for: Double(str)!)
if let finalStr = finalStr {
return finalStr
} else {
return "none"
}
}
self.formatterNumberToString("10003232.234", digits: 2) //it return 10,003,232.234
Why minimumFractionDigits not work?
Your code is working fine. The condition for minimum number of digits is met. What you probably need is to always show 2 digits. So, just add this line,
formatter.maximumFractionDigits = digits
This will display
10,003,232.23
I'm displaying a distance with one decimal, and I would like to remove this decimal in case it is equal to 0 (ex: 1200.0Km), how could I do that in swift?
I'm displaying this number like this:
let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: "%.1f", distanceFloat) + "Km"
Swift 3/4:
var distanceFloat1: Float = 5.0
var distanceFloat2: Float = 5.540
var distanceFloat3: Float = 5.03
extension Float {
var clean: String {
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
}
}
print("Value \(distanceFloat1.clean)") // 5
print("Value \(distanceFloat2.clean)") // 5.54
print("Value \(distanceFloat3.clean)") // 5.03
Swift 2 (Original answer)
let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: distanceFloat == floor(distanceFloat) ? “%.0f" : "%.1f", distanceFloat) + "Km"
Or as an extension:
extension Float {
var clean: String {
return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
}
}
Use NSNumberFormatter:
let formatter = NumberFormatter()
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 2
// Avoid not getting a zero on numbers lower than 1
// Eg: .5, .67, etc...
formatter.numberStyle = .decimal
let nums = [3.0, 5.1, 7.21, 9.311, 600.0, 0.5677, 0.6988]
for num in nums {
print(formatter.string(from: num as NSNumber) ?? "n/a")
}
Returns:
3
5.1
7.21
9.31
600
0.57
0.7
extension is the powerful way to do it.
Extension:
Code for Swift 2 (not Swift 3 or newer):
extension Float {
var cleanValue: String {
return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
}
}
Usage:
var sampleValue: Float = 3.234
print(sampleValue.cleanValue)
3.234
sampleValue = 3.0
print(sampleValue.cleanValue)
3
sampleValue = 3
print(sampleValue.cleanValue)
3
Sample Playground file is here.
Update of accepted answer for swift 3:
extension Float {
var cleanValue: String {
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
}
}
usage would just be:
let someValue: Float = 3.0
print(someValue.cleanValue) //prints 3
To format it to String, follow this pattern
let aFloat: Float = 1.123
let aString: String = String(format: "%.0f", aFloat) // "1"
let aString: String = String(format: "%.1f", aFloat) // "1.1"
let aString: String = String(format: "%.2f", aFloat) // "1.12"
let aString: String = String(format: "%.3f", aFloat) // "1.123"
To cast it to Int, follow this pattern
let aInt: Int = Int(aFloat) // "1"
When you use String(format: initializer, Swift will automatically round the final digit as needed based on the following number.
You can use an extension as already mentioned, this solution is a little shorter though:
extension Float {
var shortValue: String {
return String(format: "%g", self)
}
}
Example usage:
var sample: Float = 3.234
print(sample.shortValue)
Swift 5
for Double it's same as #Frankie's answer for float
var dec: Double = 1.0
dec.clean // 1
for the extension
extension Double {
var clean: String {
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
}
}
Swift 5.5 makes it easy
Just use the new formatted() api with a default FloatingPointFormatStyle:
let values: [Double] = [1.0, 4.5, 100.0, 7]
for value in values {
print(value.formatted(FloatingPointFormatStyle()))
}
// prints "1, 4.5, 100, 7"
In Swift 4 try this.
extension CGFloat{
var cleanValue: String{
//return String(format: 1 == floor(self) ? "%.0f" : "%.2f", self)
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.2f", self)//
}
}
//How to use - if you enter more then two-character after (.)point, it's automatically cropping the last character and only display two characters after the point.
let strValue = "32.12"
print(\(CGFloat(strValue).cleanValue)
Formatting with maximum fraction digits, without trailing zeros
This scenario is good when a custom output precision is desired.
This solution seems roughly as fast as NumberFormatter + NSNumber solution from MirekE, but one benefit could be that we're avoiding NSObject here.
extension Double {
func string(maximumFractionDigits: Int = 2) -> String {
let s = String(format: "%.\(maximumFractionDigits)f", self)
var offset = -maximumFractionDigits - 1
for i in stride(from: 0, to: -maximumFractionDigits, by: -1) {
if s[s.index(s.endIndex, offsetBy: i - 1)] != "0" {
offset = i
break
}
}
return String(s[..<s.index(s.endIndex, offsetBy: offset)])
}
}
(works also with extension Float, but not the macOS-only type Float80)
Usage: myNumericValue.string(maximumFractionDigits: 2) or myNumericValue.string()
Output for maximumFractionDigits: 2:
1.0 → "1"
0.12 → "0.12"
0.012 → "0.01"
0.0012 → "0"
0.00012 → "0"
Simple :
Int(floor(myFloatValue))
NSNumberFormatter is your friend
let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
let numberFormatter = NSNumberFormatter()
numberFormatter.positiveFormat = "###0.##"
let distance = numberFormatter.stringFromNumber(NSNumber(float: distanceFloat))!
distanceLabel.text = distance + " Km"
Here's the full code.
let numberA: Float = 123.456
let numberB: Float = 789.000
func displayNumber(number: Float) {
if number - Float(Int(number)) == 0 {
println("\(Int(number))")
} else {
println("\(number)")
}
}
displayNumber(numberA) // console output: 123.456
displayNumber(numberB) // console output: 789
Here's the most important line in-depth.
func displayNumber(number: Float) {
Strips the float's decimal digits with Int(number).
Returns the stripped number back to float to do an operation with Float(Int(number)).
Gets the decimal-digit value with number - Float(Int(number))
Checks the decimal-digit value is empty with if number - Float(Int(number)) == 0
The contents within the if and else statements doesn't need explaining.
This might be helpful too.
extension Float {
func cleanValue() -> String {
let intValue = Int(self)
if self == 0 {return "0"}
if self / Float (intValue) == 1 { return "\(intValue)" }
return "\(self)"
}
}
Usage:
let number:Float = 45.23230000
number.cleanValue()
Maybe stringByReplacingOccurrencesOfString could help you :)
let aFloat: Float = 1.000
let aString: String = String(format: "%.1f", aFloat) // "1.0"
let wantedString: String = aString.stringByReplacingOccurrencesOfString(".0", withString: "") // "1"
I am using NSDecimalNumber to format currency and want the following inputs and outputs:
9.99 --> 9.99
10 --> 10
10.00 --> 10
9.90 --> 9.90
9.9 --> 9.90
0 --> 0
0.01 --> 0.01
20 --> 20
10.01 --> 10.01
How can I do this in Swift.
EDIT: Essentially if there are cents (i.e. cents > 0) then display the cents. Otherwise, don't.
Your rule is "Display two fractional digits if either is non-zero; otherwise, display no fractional digits and no decimal point”. I would do it in the most straightforward way:
let number = NSDecimalNumber(string: "12345.00")
let formatter = NSNumberFormatter()
formatter.positiveFormat = "0.00"
let formattedString = formatter.stringFromNumber(number)!
.stringByReplacingOccurrencesOfString(".00", withString: "")
You can use NSNumberFormatter's currency formatting for this. However, there doesn't seem to be a built-in way to do rounding the way you want. Here's a workaround:
let formatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
func numToCurrency (num: Double) -> String {
if floor(num) == num {
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 0
}
else {
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
}
return formatter.stringFromNumber(num)!
}
numToCurrency(9) // "$9"
numToCurrency(9.9) // "$9.90"
Check the NSNumberFormatter class reference for further configuration options (you might need to set a locale for this formatter to automatically use the correct international currency sign for the current user).
(Answering here, as a closed question was re-directed to this one...)
Perhaps the most straightforward route, particularly since this is tagged "Swift", is to determine if it's a whole number or not:
if value.truncatingRemainder(dividingBy: 1) == 0 {
// it's a whole number,
// so format WITHOUT decimal places, e.g. $12
} else {
// it's a fraction,
// so format WITH decimal places, e.g. $12.25
}
the added benefit is avoiding issues with locales and currency formats... no search/replace of ".00" when you're in Germany, for example, where the format is ",00"
edit/update: Xcode 8.3 • Swift 3.1
extension Formatter {
static let noFractionDigits: NumberFormatter = {
let formatter = NumberFormatter()
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 0
formatter.minimumIntegerDigits = 1
return formatter
}()
static let twoFractionDigits: NumberFormatter = {
let formatter = NumberFormatter()
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
formatter.minimumIntegerDigits = 1
return formatter
}()
}
extension FloatingPoint {
var customDescription: String {
return rounded(.down) == self ?
Formatter.noFractionDigits.string(for: self) ?? "" :
Formatter.twoFractionDigits.string(for: self) ?? ""
}
}
extension String {
var double: Double { return Double(self) ?? 0 }
}
let array = ["9.99","10","10.00","9.90","9.9"]
let results = array.map { $0.double.customDescription }
results // ["9.99", "10", "10", "9.90", "9.90"]
Here's how to create a custom formatter class to handle this for you:
import Foundation
class CustomFormatter: NSNumberFormatter {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init() {
super.init()
self.locale = NSLocale.currentLocale()
self.numberStyle = .DecimalStyle
}
func isIntegerNumber(number:NSNumber) -> Bool {
var value: NSDecimal = number.decimalValue
if NSDecimalIsNotANumber(&value) { return false }
var rounded = NSDecimal()
NSDecimalRound(&rounded, &value, 0, NSRoundingMode.RoundPlain)
return NSDecimalCompare(&rounded, &value) == NSComparisonResult.OrderedSame
}
override func stringFromNumber(number: NSNumber) -> String? {
if isIntegerNumber(number) {
self.minimumFractionDigits = 0
self.maximumFractionDigits = 0
return super.stringFromNumber(number)
}
else {
self.minimumFractionDigits = 2
self.maximumFractionDigits = 2
return super.stringFromNumber(number)
}
}
}
let formatter = CustomFormatter()
formatter.stringFromNumber(NSDecimalNumber(double: 5.00)) // -> "5"
formatter.stringFromNumber(NSDecimalNumber(double: 5.01)) // -> "5.01"
formatter.stringFromNumber(NSDecimalNumber(double: 5.10)) // -> "5.10"
Thanks to this post for the proper way to test if a NSDecimal is an integer.
I think it's best to let the currencyStyle determine the maximumFractionDigits. Just set the minimumFractionDigits to 0 where desired. The code is slightly shorter, but as a bonus if you set the locale, this way will allow for languages that don't have 2 decimal places.
Using NSNumberFormatter gives you the benefit of currency symbols, decimal places and comma’s, all in the perfect places for the different locale’s.
extension NSNumber {
func currencyString() -> String? {
let formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
if self.isEqualToNumber(self.integerValue) {
formatter.minimumFractionDigits = 0
}
return formatter.stringFromNumber(self)
}
}
let inputArray: [NSDecimalNumber] = [9.99, 10, 10.00, 9.90, 0, 0.01, 20, 10.01, 0.5, 0.055, 5.0]
let outputArray: [String] = inputArray.map({return $0.currencyString() ?? "nil"})
print(outputArray)
["$9.99", "$10", "$10", "$9.90", "$0", "$0.01", "$20", "$10.01", "$0.50", "$0.06", "$5"]
Adding a locale to a NSNumberFormatter looks like this(ex. from an SKProduct object):
formatter.locale = product!.priceLocale
For an OSX app you need to add:
formatter.formatterBehavior = .Behavior10_4
I have float value that ends in .0 or .5 (for example 10.0 or 10.5). If it ends in .0 I would like to eliminate the trailing zero. What is the easiest way to do this in Swift?
func myFunction() {
var string = pickerData[picker.selectedRowInComponent(0)]
var float = ((string as NSString).floatValue - 45) / 2
label.text = float.description
}
You should use NSNumberFormatter() to format your numbers as follow:
extension Double {
var formatted:String {
let formatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
// you can set the minimum fraction digits to 0
formatter.minimumFractionDigits = 0
// and set the maximum fraction digits to 1
formatter.maximumFractionDigits = 1
return formatter.stringFromNumber(self) ?? ""
}
}
10.5.formatted // "10.5"
10.0.formatted // "10"
In your case it would look like this:
label.text = float.formatted
I need to create a String with format which can convert Int, Int64, Double, etc types into String. Using Objective-C, I can do it by:
NSString *str = [NSString stringWithFormat:#"%d , %f, %ld, %#", INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, STRING_VALUE];
How to do same but in Swift?
I think this could help you:
import Foundation
let timeNow = time(nil)
let aStr = String(format: "%#%x", "timeNow in hex: ", timeNow)
print(aStr)
Example result:
timeNow in hex: 5cdc9c8d
nothing special
let str = NSString(format:"%d , %f, %ld, %#", INT_VALUE, FLOAT_VALUE, LONG_VALUE, STRING_VALUE)
let str = "\(INT_VALUE), \(FLOAT_VALUE), \(DOUBLE_VALUE), \(STRING_VALUE)"
Update: I wrote this answer before Swift had String(format:) added to it's API. Use the method given by the top answer.
No NSString required!
String(format: "Value: %3.2f\tResult: %3.2f", arguments: [2.7, 99.8])
or
String(format:"Value: %3.2f\tResult: %3.2f", 2.7, 99.8)
I would argue that both
let str = String(format:"%d, %f, %ld", INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE)
and
let str = "\(INT_VALUE), \(FLOAT_VALUE), \(DOUBLE_VALUE)"
are both acceptable since the user asked about formatting and both cases fit what they are asking for:
I need to create a string with format which can convert int, long, double etc. types into string.
Obviously the former allows finer control over the formatting than the latter, but that does not mean the latter is not an acceptable answer.
First read Official documentation for Swift language.
Answer should be
var str = "\(INT_VALUE) , \(FLOAT_VALUE) , \(DOUBLE_VALUE), \(STRING_VALUE)"
println(str)
Here
1) Any floating point value by default double
EX.
var myVal = 5.2 // its double by default;
-> If you want to display floating point value then you need to explicitly define such like a
EX.
var myVal:Float = 5.2 // now its float value;
This is far more clear.
let INT_VALUE=80
let FLOAT_VALUE:Double= 80.9999
let doubleValue=65.0
let DOUBLE_VALUE:Double= 65.56
let STRING_VALUE="Hello"
let str = NSString(format:"%d , %f, %ld, %#", INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, STRING_VALUE);
println(str);
The accepted answer is definitely the best general solution for this (i.e., just use the String(format:_:) method from Foundation) but...
If you are running Swift ≥ 5, you can leverage the new StringInterpolationProtocol protocol to give yourself some very nice syntax sugar for common string formatting use cases in your app.
Here is how the official documentation summarizes this new protocol:
Represents the contents of a string literal with interpolations while it’s being built up.
Some quick examples:
extension String.StringInterpolation {
/// Quick formatting for *floating point* values.
mutating func appendInterpolation(float: Double, decimals: UInt = 2) {
let floatDescription = String(format: "%.\(decimals)f%", float)
appendLiteral(floatDescription)
}
/// Quick formatting for *hexadecimal* values.
mutating func appendInterpolation(hex: Int) {
let hexDescription = String(format: "0x%X", hex)
appendLiteral(hexDescription)
}
/// Quick formatting for *percents*.
mutating func appendInterpolation(percent: Double, decimals: UInt = 2) {
let percentDescription = String(format: "%.\(decimals)f%%", percent * 100)
appendLiteral(percentDescription)
}
/// Formats the *elapsed time* since the specified start time.
mutating func appendInterpolation(timeSince startTime: TimeInterval, decimals: UInt = 2) {
let elapsedTime = CACurrentMediaTime() - startTime
let elapsedTimeDescription = String(format: "%.\(decimals)fs", elapsedTime)
appendLiteral(elapsedTimeDescription)
}
}
which could be used as:
let number = 1.2345
"Float: \(float: number)" // "Float: 1.23"
"Float: \(float: number, decimals: 1)" // "Float: 1.2"
let integer = 255
"Hex: \(hex: integer)" // "Hex: 0xFF"
let rate = 0.15
"Percent: \(percent: rate)" // "Percent: 15.00%"
"Percent: \(percent: rate, decimals: 0)" // "Percent: 15%"
let startTime = CACurrentMediaTime()
Thread.sleep(forTimeInterval: 2.8)
"∆t was \(timeSince: startTime)" // "∆t was 2.80s"
"∆t was \(timeSince: startTime, decimals: 0)" // "∆t was 3s"
This was introduced by SE-0228, so please be sure to read the original proposal for a deeper understanding of this new feature. Finally, the protocol documentation is helpful as well.
I know a lot's of time has passed since this publish, but I've fallen in a similar situation and create a simples class to simplify my life.
public struct StringMaskFormatter {
public var pattern : String = ""
public var replecementChar : Character = "*"
public var allowNumbers : Bool = true
public var allowText : Bool = false
public init(pattern:String, replecementChar:Character="*", allowNumbers:Bool=true, allowText:Bool=true)
{
self.pattern = pattern
self.replecementChar = replecementChar
self.allowNumbers = allowNumbers
self.allowText = allowText
}
private func prepareString(string:String) -> String {
var charSet : NSCharacterSet!
if allowText && allowNumbers {
charSet = NSCharacterSet.alphanumericCharacterSet().invertedSet
}
else if allowText {
charSet = NSCharacterSet.letterCharacterSet().invertedSet
}
else if allowNumbers {
charSet = NSCharacterSet.decimalDigitCharacterSet().invertedSet
}
let result = string.componentsSeparatedByCharactersInSet(charSet)
return result.joinWithSeparator("")
}
public func createFormattedStringFrom(text:String) -> String
{
var resultString = ""
if text.characters.count > 0 && pattern.characters.count > 0
{
var finalText = ""
var stop = false
let tempString = prepareString(text)
var formatIndex = pattern.startIndex
var tempIndex = tempString.startIndex
while !stop
{
let formattingPatternRange = formatIndex ..< formatIndex.advancedBy(1)
if pattern.substringWithRange(formattingPatternRange) != String(replecementChar) {
finalText = finalText.stringByAppendingString(pattern.substringWithRange(formattingPatternRange))
}
else if tempString.characters.count > 0 {
let pureStringRange = tempIndex ..< tempIndex.advancedBy(1)
finalText = finalText.stringByAppendingString(tempString.substringWithRange(pureStringRange))
tempIndex = tempIndex.advancedBy(1)
}
formatIndex = formatIndex.advancedBy(1)
if formatIndex >= pattern.endIndex || tempIndex >= tempString.endIndex {
stop = true
}
resultString = finalText
}
}
return resultString
}
}
The follow link send to the complete source code:
https://gist.github.com/dedeexe/d9a43894081317e7c418b96d1d081b25
This solution was base on this article:
http://vojtastavik.com/2015/03/29/real-time-formatting-in-uitextfield-swift-basics/
There is a simple solution I learned with "We <3 Swift" if you can't either import Foundation, use round() and/or does not want a String:
var number = 31.726354765
var intNumber = Int(number * 1000.0)
var roundedNumber = Double(intNumber) / 1000.0
result: 31.726
Use this following code:
let intVal=56
let floatval:Double=56.897898
let doubleValue=89.0
let explicitDaouble:Double=89.56
let stringValue:"Hello"
let stringValue="String:\(stringValue) Integer:\(intVal) Float:\(floatval) Double:\(doubleValue) ExplicitDouble:\(explicitDaouble) "
The beauty of String(format:) is that you can save a formatting string and then reuse it later in dozen of places. It also can be localized in this single place. Where as in case of the interpolation approach you must write it again and again.
Simple functionality is not included in Swift, expected because it's included in other languages, can often be quickly coded for reuse. Pro tip for programmers to create a bag of tricks file that contains all this reuse code.
So from my bag of tricks we first need string multiplication for use in indentation.
#inlinable func * (string: String, scalar: Int) -> String {
let array = [String](repeating: string, count: scalar)
return array.joined(separator: "")
}
and then the code to add commas.
extension Int {
#inlinable var withCommas:String {
var i = self
var retValue:[String] = []
while i >= 1000 {
retValue.append(String(format:"%03d",i%1000))
i /= 1000
}
retValue.append("\(i)")
return retValue.reversed().joined(separator: ",")
}
#inlinable func withCommas(_ count:Int = 0) -> String {
let retValue = self.withCommas
let indentation = count - retValue.count
let indent:String = indentation >= 0 ? " " * indentation : ""
return indent + retValue
}
}
I just wrote this last function so I could get the columns to line up.
The #inlinable is great because it takes small functions and reduces their functionality so they run faster.
You can use either the variable version or, to get a fixed column, use the function version. Lengths set less than the needed columns will just expand the field.
Now you have something that is pure Swift and does not rely on some old objective C routine for NSString.
Since String(format: "%s" ...) is crashing at run time, here is code to allow write something like "hello".center(42); "world".alignLeft(42):
extension String {
// note: symbol names match to nim std/strutils lib:
func align (_ boxsz: UInt) -> String {
self.withCString { String(format: "%\(boxsz)s", $0) }
}
func alignLeft (_ boxsz: UInt) -> String {
self.withCString { String(format: "%-\(boxsz)s", $0) }
}
func center (_ boxsz: UInt) -> String {
let n = self.count
guard boxsz > n else { return self }
let padding = boxsz - UInt(n)
let R = padding / 2
guard R > 0 else { return " " + self }
let L = (padding%2 == 0) ? R : (R+1)
return " ".withCString { String(format: "%\(L)s\(self)%\(R)s", $0,$0) }
}
}
Success to try it:
var letters:NSString = "abcdefghijkl"
var strRendom = NSMutableString.stringWithCapacity(strlength)
for var i=0; i<strlength; i++ {
let rndString = Int(arc4random() % 12)
//let strlk = NSString(format: <#NSString#>, <#CVarArg[]#>)
let strlk = NSString(format: "%c", letters.characterAtIndex(rndString))
strRendom.appendString(String(strlk))
}