преобразовать число в формат с разделителем, - PullRequest
0 голосов
/ 04 мая 2019

Как преобразовать числовой формат с разделением,

Пример Resultant String

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

Ответы [ 3 ]

2 голосов
/ 04 мая 2019

Либо установите правильный (который использует этот стиль для форматирования) языковой стандарт, либо установите десятичный разделитель и разделитель группировки в экземпляре средства форматирования, поскольку не все языковые стандарты могут использовать одни и те же разделители.

Затем вам также нужно установить максимальное количество цифр дроби, если вы используете float (по некоторым причинам это не нужно для 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

0 голосов
/ 04 мая 2019

Есть три вопроса:

  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() ?? ""
    
0 голосов
/ 04 мая 2019

См. Это: - как добавить запятые к числу в swift? введите описание ссылки здесь

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)
    }
...