I've been investigating and trying to code a compact number format otherwise known as a short scale formatter or a humanizing big numbers into smaller ones in Swift.
I suddenly thought rather than trying to recode the wheel maybe Unicode
already solved this issue and saw that there is indeed some code to compact larger numbers.
In the open-source code for Apple Swift on Github there is a reference to compactdecimalformat.h
at:
In it, it refers to numberformatter.h; which I found a reference from Unicode ICU 67.1 at:
https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/numberformatter_8h.html
However, I am not sure how to use it. I've imported Darwin, but I am not sure how to actually call compactdecimalformat
or the public identifier DecimalFormat
I'd like to run some number tests against it to see if it is what I'm looking for in terms of compacting / short scaling numbers.
Thus my question is, how do you include and use the compactdecimalnumber.h file that comes as part of the Darwin import?
With thanks
edit: I think upon reading the code and comments the .h file only handles really big numbers?
I don't think there is such formatter in Swift but you can subclass NumberFormatter and create your own CompactNumberFormatter if needed:
class CompactDecimalFormatter: NumberFormatter {
override func string(for obj: Any?) -> String? {
guard var value = (obj as? NSNumber)?.doubleValue else { return nil }
let suffixes = ["", "k", "m", "b","t"]
var index = suffixes.startIndex
while index < suffixes.endIndex && value.magnitude >= 1000 {
index = suffixes.index(after: index)
value /= 1000
}
formatter.positiveSuffix = suffixes[index]
formatter.negativeSuffix = suffixes[index]
return formatter.string(for: value)
}
private let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.roundingMode = .down
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 1
return formatter
}()
// You can override all the properties you thing you might need
override var minimumIntegerDigits: Int {
get { formatter.minimumIntegerDigits }
set { formatter.minimumIntegerDigits = newValue }
}
override var maximumIntegerDigits: Int {
get { formatter.maximumIntegerDigits }
set { formatter.maximumIntegerDigits = newValue }
}
override var minimumFractionDigits: Int {
get { formatter.minimumFractionDigits }
set { formatter.minimumFractionDigits = newValue }
}
override var maximumFractionDigits: Int {
get { formatter.maximumFractionDigits }
set { formatter.maximumFractionDigits = newValue }
}
override var positivePrefix: String! {
get { formatter.positivePrefix }
set { formatter.positivePrefix = newValue }
}
override var negativePrefix: String! {
get { formatter.negativePrefix }
set { formatter.negativePrefix = newValue }
}
override var roundingMode: RoundingMode {
get{ formatter.roundingMode }
set{ formatter.roundingMode = newValue }
}
// or disable them
override var numberStyle: Style { get { .decimal } set { } }
override var positiveSuffix: String! { get { "" } set { } }
override var negativeSuffix: String! { get { "" } set { } }
}
let formatter = CompactDecimalFormatter()
formatter.string(for: 2500) // "2.5k"