You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用FormatStyle API格式化带SI单位的大额货币数值

用FormatStyle API实现带SI单位的大额货币格式化

可以通过自定义FormatStyle来实现这个需求,原生的货币格式化组件不直接支持SI单位缩写,但我们可以封装一个组合式的格式器,同时兼顾货币符号本地化、数值缩放和SI单位显示。

实现思路

  • 定义SI单位对应的缩放规则(比如1M对应10^6)
  • 对输入数值进行缩放,匹配对应的SI单位
  • 使用原生货币格式化处理缩放后的数值,确保本地化的货币符号正确
  • 将SI单位符号追加到格式化后的字符串末尾

完整代码实现

struct CurrencySIFormatStyle: FormatStyle {
    typealias FormatInput = Double
    typealias FormatOutput = String
    
    let currencyCode: String
    let precision: FloatingPointFormatStyle<Double>.Precision
    
    func format(_ value: Double) -> String {
        // 定义SI单位阈值、缩放因子和符号
        let siUnits: [(threshold: Double, divisor: Double, symbol: String)] = [
            (1_000_000_000, 1_000_000_000, "B"),
            (1_000_000, 1_000_000, "M"),
            (1_000, 1_000, "k"),
            (0, 1, "")
        ]
        
        // 匹配当前数值对应的SI单位
        let matchedUnit = siUnits.first { abs(value) >= $0.threshold } ?? siUnits.last!
        let scaledValue = value / matchedUnit.divisor
        
        // 利用原生货币格式化处理缩放后的数值,保证本地化适配
        let currencyFormatter = FloatingPointFormatStyle<Double>.currency(code: currencyCode)
            .precision(precision)
        
        let formattedCurrency = currencyFormatter.format(scaledValue)
        return formattedCurrency + matchedUnit.symbol
    }
}

// 扩展FormatStyle,提供便捷调用方式
extension FormatStyle where Self == CurrencySIFormatStyle {
    /// 带SI单位的货币格式化器
    /// - Parameters:
    ///   - code: 货币代码(如"usd"、"eur")
    ///   - precision: 数值精度设置
    static func currencySI(code: String, precision: FloatingPointFormatStyle<Double>.Precision = .significantDigits(2)) -> CurrencySIFormatStyle {
        CurrencySIFormatStyle(currencyCode: code, precision: precision)
    }
    
    // 对应原有需求的美元SI格式化器
    static var dollarsSI: CurrencySIFormatStyle {
        .currencySI(code: "usd", precision: .significantDigits(2))
    }
}

使用示例

// 大额数值格式化
let twentyMillion = Double(20_000_000)
print(twentyMillion.formatted(.dollarsSI)) // 输出 "$20M"

// 更大数值
let onePointFiveBillion = Double(1_500_000_000)
print(onePointFiveBillion.formatted(.dollarsSI)) // 输出 "$1.5B"

// 小额数值(不触发SI单位)
let fiveHundred = Double(500)
print(fiveHundred.formatted(.dollarsSI)) // 输出 "$500"

// 负数处理
let negativeTenThousand = Double(-10_000)
print(negativeTenThousand.formatted(.dollarsSI)) // 输出 "-$10k"

// 本地化适配(比如切换到英国Locale)
Locale.current = Locale(identifier: "en_GB")
print(twentyMillion.formatted(.dollarsSI)) // 输出 "US$20M"

扩展说明

  • 单位扩展:如果需要支持更大/更小的SI单位(如万亿"T"、毫"m"),只需在siUnits数组中添加对应的条目即可
  • 精度调整:可以通过修改precision参数控制数值显示精度,比如.fractionLength(0)强制显示整数,.significantDigits(3)显示3位有效数字
  • 本地化兼容:依赖原生currency(code:)的本地化能力,货币符号会根据当前Locale自动调整,符合不同地区的显示习惯

内容的提问来源于stack exchange,提问作者Rob Napier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:01:00