【问题标题】:convert number formate with separator ,用分隔符转换数字格式,
【发布时间】:2019-09-22 18:41:17
【问题描述】:

如何将数字格式转换为以 , 分隔的格式

示例 结果字符串

 "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"

【问题讨论】:

  • StringValue 是什么?
  • @ielyamani 字符串值为“38963.26”
  • CGFloatValue 是什么?它是您为字符串定义的扩展吗?您可以编辑您的问题而不是在 cmets 中回复吗?
  • CGFloatValue 用于将String转换为floatValue。
  • 价值指标有些国家说 10 万,而其他国家说 10 万。在我的情况下,它是这样的“10,13,321.22”。

标签: ios swift number-formatting


【解决方案1】:

要么设置一个适当的(使用这种格式的格式)语言环境,要么在你的格式化程序实例上设置小数和分组分隔符,因为并非所有的语言环境都可能使用相同的分隔符。

如果您使用浮点数,您还需要设置最大小数位数(出于某种原因,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

【讨论】:

  • 它对我的解决方案 Joakim Danielson 有帮助。但是为什么在对话输出“38,863.262”时添加了额外的十进制值?任何想法都可以在下面发表评论。
  • @kiran 我不知道为什么 Float 会以这种方式运行,正如我在答案中所写的,它适用于 Double,看起来 NumberFormatter 类有问题。
  • 这个答案涉及到一个深奥的问题,即某些(甚至很小的)十进制数根本无法在浮点数中完美再现。但是,这是一个相关(但恕我直言,更简单)的问题,他只是超过了significandBitCountFloat
【解决方案2】:

请参考:- 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)
    }

【讨论】:

  • 代替string(from:)NSNumber,使用string(for:)并直接使用Double,绕过NSNumber。此外,结果不是可选的。
【解决方案3】:

存在三个问题:

  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: $0) }
        }
    }
    

    然后

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    相关资源
    最近更新 更多