【问题标题】:How to properly reduce scale and format a Float value in Swift?如何在 Swift 中正确减小比例并格式化浮点值?
【发布时间】:2022-11-02 18:59:50
【问题描述】:

我正在尝试正确减小比例,格式化浮点值并将其作为 Swift 中的字符串返回。

例如:

let value: Float = 4.8962965

// formattedFalue should be 4.90 or 4,90 based on localization
let formattedValue = value.formatNumber()

这是我所做的:

extension Float {

func reduceScale(to places: Int) -> Float {
      let multiplier = pow(10, Float(places))
      let newDecimal = multiplier * self // move the decimal right
      let truncated = Float(Int(newDecimal)) // drop the fraction
      let originalDecimal = truncated / multiplier // move the decimal back                 return originalDecimal
 }

func formatNumber() -> String {
      let num = abs(self)

      let numberFormatter = NumberFormatter()
      numberFormatter.usesGroupingSeparator = true
      numberFormatter.minimumFractionDigits = 0
      numberFormatter.maximumFractionDigits = 2
      numberFormatter.roundingMode = .up
      numberFormatter.numberStyle = .decimal
      numberFormatter.locale = // we take it from app settings 

      let formatted = num.reduceScale(to: 2)
      let returningString = numberFormatter.string(from: NSNumber(value: formatted))!
      return "\(returningString)"

}

}

但是当我使用此代码时,我得到 4.89(或 4,89,具体取决于本地化),而不是我期望的 4.90(或 4,90)。

提前致谢。

【问题讨论】:

  • 删除不必要的 reduceScale 方法,它可能会按预期工作。您正在将小数截断为 4.89,它不能再四舍五入了(它已经四舍五入了)。
  • 嗨@Sulthan 感谢您的回复。我删除了 reduceScale 方法,现在我直接返回 let returnedString = currencyFormatter.string(from: NSNumber(value: num))!但我得到 4.9。
  • 那是因为您指定了minimumFractionDigits = 0。如果您总是想显示两位小数,则必须设置minimumFractionDigits = 2
  • 非常感谢@Sulthan 现在它按预期工作!我并不总是希望 minimumFractionDigits 为 0,所以我将它作为参数动态传递。

标签: swift


【解决方案1】:

按照 Sulthan 的建议解决,方法是删除 reduceScale 方法并将 minimumFractionDigits 设置为 2。

【讨论】:

    【解决方案2】:

    得到 4.89 是因为 reduceScale(to:) 将数字转换为 4.89(实际上,可能是 4.89000something,因为 4.89 不能精确地表示为二进制浮点数)。当数字格式化程序将其截断到小数点后两位时,它自然会向下舍入。

    实际上,您根本不需要reduceScale(to:),因为数字格式化程序的舍入功能会为您完成。

    最后的字符串插值也是不必要的,因为NumberFormatter.string(from:) 的结果会自动桥接到String?

    此外(参见下面 Dávid Pásztor 和 Sulthan 的 cmets)您可以使用 string(for:) 来避免 NSNumber 转换。

    这就是你需要的

    import Foundation
    
    extension Float {
    
        func formatNumber() -> String {
              let num = abs(self)
    
              let numberFormatter = NumberFormatter()
              numberFormatter.usesGroupingSeparator = true
              numberFormatter.minimumFractionDigits = 0
              numberFormatter.maximumFractionDigits = 2
              numberFormatter.roundingMode = .up
              numberFormatter.numberStyle = .decimal
              numberFormatter.locale = whatever
              return numberFormatter.string(for: num)!
        }
    }
    
    let value: Float = 4.8962965
    
    // formattedFalue should be 4.90 or 4,90 based on localization
    let formattedValue = value.formatNumber() // "4.9"
    

    【讨论】:

    • 您也可以使用string(from:) 来避免使用NSNumber
    • @Sulthan 我在操场上尝试过,它错误地说它需要一个NSNumber
    • @JeremyP string(for:) 是采用任何数字类型而不仅仅是 NSNumber 的替代方案
    • @DávidPásztor 谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-18
    • 2016-10-05
    • 2019-12-28
    • 2011-09-08
    • 2018-09-14
    相关资源
    最近更新 更多