Search code examples
swiftnumberformatter

Remove all numbers before the period in a Double with NumberFormatter not working - Swift


I'm trying to remove all digits before the . period in a Double using NumberFormatter but for some reason, it only removes it if the digits are zeros.

Is it normal that when stating formatter.minimumIntegerDigits = 0 it doesn't remove all digits before the . unless they're zeros?

func formatDoubleAsStringFraction(number: Double)->String{
    var formatter = NumberFormatter()
    formatter.locale = NSLocale.current
    formatter.minimumFractionDigits = 2 // two digits after the decimal point
    formatter.minimumIntegerDigits = 0 // this will remove digits before Idecimal point
    formatter.numberStyle = .decimal
    let formatedNumber = formatter.string(for: number)
    
    return formatedNumber!
}


formatDoubleAsStringFraction(number: 0.99) // outputs: .99
formatDoubleAsStringFraction(number: 000.99) // outputs: .99

formatDoubleAsStringFraction(number: 1.99) // outputs: 1.99 - why it doesn't remove the 1?
formatDoubleAsStringFraction(number: 123.99) // outputs: 123.99 - why it doesn't remove the 123?

Solution

  • Try setting maximumIntegerDigits = 0

    That should force your output to have no integer digits. It worked in a quick test I did.

    Edit:

    This code:

    func formatDoubleAsStringFraction(number: Double)->String{
        let formatter = NumberFormatter()
        formatter.locale = NSLocale.current
        formatter.minimumFractionDigits = 2 // at least 2 digits after the decimal point
        formatter.maximumFractionDigits = 2 // no more than two digits after the decimal point
        formatter.maximumIntegerDigits = 0 // this will remove digits before the decimal point
        formatter.numberStyle = .decimal
        let formatedNumber = formatter.string(for: number)
    
        return formatedNumber!
    }
    
    for _ in 1...10 {
        let value = Double.random(in: -100...100)
        print("formatDoubleAsStringFraction(\(value)) = \(formatDoubleAsStringFraction(number:value))")
    }
    

    Yields test output like this:

    formatDoubleAsStringFraction(4.157493934834335) = .16
    formatDoubleAsStringFraction(-87.6652867247289) = -.67
    formatDoubleAsStringFraction(-23.442326432705002) = -.44
    formatDoubleAsStringFraction(-49.424727272130696) = -.42
    formatDoubleAsStringFraction(44.03922384656289) = .04
    formatDoubleAsStringFraction(46.795543920754454) = .80
    formatDoubleAsStringFraction(42.842058609346736) = .84
    formatDoubleAsStringFraction(-44.274898907193275) = -.27
    formatDoubleAsStringFraction(93.86270874357706) = .86
    formatDoubleAsStringFraction(16.953208660898483) = .95
    

    Which seems to match your desired output.

    (Note that if you want exactly 2 fractional decimal digits, you probably want to set both minimumFractionDigits and maximumFractionDigits.)