转换带分隔符的数字格式,

convert number formate with separator ,

如何转换以 ,

分隔的数字甲酸

例子 结果字符串

 "38963.26" value into "38,863.26"
  "1013321.22" Value into "10,13,321.22"

//MARK:- Seperator number formate 1000 - 1,000
extension Formatter {
    static let withSeparator: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.groupingSeparator = ","
        formatter.numberStyle = .decimal
        return formatter
    }()
}

extension BinaryFloatingPoint {
    var formattedWithSeparator: String {
        return Formatter.withSeparator.string(for: self) ?? ""
    }
}


let resultValue = StringValue.CGFloatValue()?.formattedWithSeparator
print("Resultant", resultValue!)

CGFloatVaule 将 String 转换为 floatValue 的默认方法。 与 String.floatValue 相同。

对于值 "38963.26" 给出了结果值 "38,963.262" 我想知道为什么它像十进制的额外 2。

print("38963.26".CGFloatValue()!.formattedWithSeparator)
Output "38,863.262"

参考这个:- how to add commas to a number in swift?enter link description here

let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal

let numberString = "38963.26"
if let number = Double(numberString),
    let formattedNumber = numberFormatter.string(from: NSNumber(value: number)) {
        let formattedString = "\(formattedNumber)"
        print(formattedString)
    }

要么设置适当的(使用此样式进行格式设置)区域设置,要么在格式化程序实例上同时设置小数点和分组分隔符,因为并非所有区域设置都可能使用相同的分隔符。

然后如果您使用浮点数,您还需要设置小数位数的最大值(由于某些原因 Double 不需要)

let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.locale = Locale(identifier: "en_US")
formatter.maximumFractionDigits = 2
if let str = formatter.string(for: Float(numberString)) {
    print(str)
}


let formatter = NumberFormatter()
formatter.groupingSeparator = ","
formatter.decimalSeparator = "."
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
if let str = formatter.string(for: Float(numberString)) {
    print(str)
}

两者都产生

38,963.26

存在三个问题:

  1. 显式分组分隔符的使用。

    强制使用千位分隔符“,”会适得其反。如果设备所在的区域设置已经是默认设置,则您无需指定它。而且,如果设备所在的区域设置不是默认设置,那么对于不习惯看到“,”千分之一分隔符的用户来说,这将非常令人困惑。更糟糕的是,如果您要覆盖分组分隔符,您也应该覆盖小数点分隔符。如果这是要在用户界面中显示的字符串,我建议不要触摸分组分隔符(或任何这些属性):

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

    如果你真的想强制使用 , 作为分组分隔符和 . 作为小数点分隔符(即使用户可能处于一个你可能会非常困惑的语言环境中在用户界面中),您应该继续将语言环境更改为您想要的任何内容,例如

    static let decimal: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.locale = Locale(identifier: "en_US") // or "en_IN" or whatever
        return formatter
    }()
    
  2. 小数位数。

    如果你总是想要小数点后两位,那么:

    static let decimal: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.minimumFractionDigits = 2
        formatter.maximumFractionDigits = 2
        return formatter
    }()
    

    通过设置最小小数位数,可以确保 42.1 显示为“42.10”。通过设置最大小数位数,可以确保 42.33333 显示为“42.33”。

  3. 将字符串转换为二进制浮点数并返回字符串所产生的问题。

    小数位的根本问题是您要将字符串转换为二进制浮点数。如果您使用 Double,您将比使用 Float/CGFloat 捕获更多的有效数字,但是在将字符串转换为二进制浮点数时仍然会引入舍入错误表示。 Float 在第 7 个有效小数位开始引入转换错误。 Double 将转换错误推迟到第 15 个有效十进制数字。

    您可以考虑使用一种数字格式,它最多可以捕获 38 位数字而不会出现舍入问题,即 Decimal。因此:

    extension NumberFormatter {
        static let decimal: NumberFormatter = {
            let formatter = NumberFormatter()
            formatter.numberStyle = .decimal
            // specify locale and/or fraction digits as needed
            return formatter
        }()
    }
    
    extension String {
        func decimalFormatted() -> String? {
            return Decimal(string: self).flatMap { NumberFormatter.decimal.string(for: [=13=]) }
        }
    }
    

    然后

    let string = "38963.26"
    let foo = string.decimalFormatted() ?? ""