NumberFormatter使用有效数字时不遵循minimumFractionDigits问题求助
解决NumberFormatter有效数字与最小小数位数冲突的问题
我太懂你遇到的这个坑了——NumberFormatter在同时设置有效数字和小数位数规则时,优先级逻辑确实有点反直觉,直接混合用这两组属性根本达不到你要的效果。咱们直接针对你的需求来实现一个精准的解决方案。
先明确你的格式化规则
你需要的是:
- 如果数值的小数部分超过2位:以6位有效数字显示
- 否则:保留原数值,且小数部分至少显示2位(比如
1→1.00,1.2→1.20,1.23保持1.23)
解决方案:分情况处理
核心思路是先判断当前数值的小数部分是否超过2位,再分别应用对应的格式化规则,避免NumberFormatter的规则冲突。下面是完整的NSNumber扩展实现:
extension NSNumber { func significantFormattedString(minimumFractionDigits: Int = 2, maximumSignificantDigits: Int = 6) -> String { // 用固定locale避免不同地区的小数点/千分位差异 let posixLocale = Locale(identifier: "en_US_POSIX") // 第一步:判断小数部分是否超过2位 let fractionCheckFormatter = NumberFormatter() fractionCheckFormatter.locale = posixLocale fractionCheckFormatter.minimumFractionDigits = minimumFractionDigits fractionCheckFormatter.maximumFractionDigits = minimumFractionDigits guard let formattedFractionString = fractionCheckFormatter.string(from: self), let formattedFractionNumber = fractionCheckFormatter.number(from: formattedFractionString), formattedFractionNumber.doubleValue != self.doubleValue else { // 情况1:小数部分≤2位,保证至少显示2位小数,同时保留原有的小数精度 let resultFormatter = NumberFormatter() resultFormatter.locale = posixLocale resultFormatter.minimumFractionDigits = minimumFractionDigits resultFormatter.maximumFractionDigits = 10 // 设置足够大的上限,保留原小数部分 resultFormatter.numberStyle = .decimal return resultFormatter.string(from: self) ?? "\(self.doubleValue)" } // 情况2:小数部分>2位,用6位有效数字格式化 let significantFormatter = NumberFormatter() significantFormatter.locale = posixLocale significantFormatter.minimumSignificantDigits = 1 significantFormatter.maximumSignificantDigits = maximumSignificantDigits significantFormatter.numberStyle = .decimal return significantFormatter.string(from: self) ?? "\(self.doubleValue)" } }
代码逻辑解释
- 小数位数判断:先用一个临时Formatter把数值强制保留2位小数,再转回数字和原数值比较。如果两者相等,说明原数值的小数部分本来就≤2位;反之则超过2位。
- 小数部分≤2位的处理:设置
minimumFractionDigits=2,同时把maximumFractionDigits设为一个足够大的值(比如10),这样既保证了至少2位小数,又不会截断原有的小数部分(比如1.23会保留为1.23,而不是被强制转成1.20)。 - 小数部分>2位的处理:直接启用有效数字规则,设置最大6位有效数字,让Formatter自动处理成符合要求的格式。
测试用例示例
| 原数值 | 格式化结果 |
|---|---|
| 1.0 | "1.00" |
| 1.2 | "1.20" |
| 1.23 | "1.23" |
| 1.234 | "1.234" |
| 1.234567 | "1.23457" |
| 0.0001234567 | "0.000123457" |
| 123456.7 | "123457" |
为什么不能直接混合设置?
因为NumberFormatter中,当你设置了minimumSignificantDigits和maximumSignificantDigits后,minimumFractionDigits和maximumFractionDigits的规则会被忽略——它会优先按照有效数字来格式化,完全不会考虑你设置的最小小数位数要求,这就是你之前遇到问题的核心原因。
内容的提问来源于stack exchange,提问作者peakingcube
相关产品推荐
相关产品推荐

