Benjamin B.
Benjamin B.

Reputation: 793

Swift, converting a number to string, number gets rounded down

I'm having a bit of issue with my code...right now, I am passing a string containing a bunch of numbers, to get converted to a number, comma separators added, then converted back to a string for output. When I add a decimal to my string and pass it in, a number like 996.3658 get truncated to 996.366...

"currentNumber" is my input value, "textOutputToScreen" is my output...

func formatNumber() {

    let charset = CharacterSet(charactersIn: ".")

    if let _ = currentNumber.rangeOfCharacter(from: charset) {
        if let number = Float(currentNumber) {

            let numberFormatter = NumberFormatter()
            numberFormatter.numberStyle = .decimal
            guard let formattedNumber = numberFormatter.string(from: NSNumber(value: number)) else { return }
            textOutputToScreen = String(formattedNumber)
        }
    }
    else {
        if let number = Int(currentNumber) {

            let numberFormatter = NumberFormatter()
            numberFormatter.numberStyle = .decimal
            guard let formattedNumber = numberFormatter.string(from: NSNumber(value: number)) else { return }
            textOutputToScreen = String(formattedNumber)
        }
    }   
}

Thank you in advance for your help!

Upvotes: 0

Views: 252

Answers (1)

Leo Dabus
Leo Dabus

Reputation: 236260

The issue there is that you have to set your NumberFormatter minimumFractionDigits to 4. Btw there is no need to initialize a NSNumber object. You can use Formatters string(for: Any) method and pass your Float. Btw I would use a Double (64-bit) instead of a Float (32-bit) and there is no need to initialize a new string g from your formattedNumber object. It is already a String.

Another thing is that you don't need to know the location of the period you can simply use contains instead of rangeOfCharacter method. Your code should look something like this:


extension Formatter {
    static let number: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        return formatter
    }()
}

func formatNumber(from string: String) -> String? {
    if string.contains(".") {
        guard let value = Double(string) else { return nil }
        Formatter.number.minimumFractionDigits = 4
        return Formatter.number.string(for: value)
    } else {
        guard let value = Int(string) else { return nil }
        Formatter.number.minimumFractionDigits = 0
        return Formatter.number.string(for: value)
    }
}

let label = UILabel()
let currentNumber = "996.3658"
label.text = formatNumber(from: currentNumber)  // "996.3658\n"

If you would like to assign the result to your var instead of a label

if let formatted = formatNumber(from: currentNumber) {
    textOutputToScreen = formatted
}

Upvotes: 3

Related Questions