问题描述
在SwiftUI应用中,发现Text显示的金额为 inf。

inf 是 infinity(无限大)的缩写,表示一个无限大数值。
这一问题通常是除 0 导致的。
例如:
let result = 1.0 / 0.0 // result 是 inf
这里的result因为除0,导致返回的值超出了Double的最大表示范围。因为除以0,是数字上趋近于无穷大,Swift就会给出inf。
通过排查定位到问题代码:
if let rate = result.filter({ $0.symbol == currency.symbol}).first?.rate, let localRate = result.first(where: { $0.symbol == appStorage.localCurrency })?.rate,rate > 0,
localRate > 0 {
let amount = currency.amount / rate * localRate
calculateCount += amount
}
在这段代码,amount涉及除汇率数据,最后amount通过叠加calculateCount,最后在Text中显示的也是calculateCount的值。
通过新增调试代码:
// 确保这个计算结果是正常数值(非 inf 非 nan)
if amount.isFinite {
calculateCount += amount
} else {
print("非法金额(inf 或 nan)在日期:\(date),symbol: \(currency.symbol ?? ""), rate:\(rate)")
}
发现输出的内容为:
非法金额(inf 或 nan)在日期:2000-07-11 16:00:00 +0000,symbol: BGN, rate:0.0
因为rate为0,所以在除以0之后,数值变成了inf。
解决方案
解决方案有两种:
一种是限制被除数的范围,要求大于0或者不等于0:
if let rate = result.filter({ $0.symbol == currency.symbol}).first?.rate, let localRate = result.first(where: { $0.symbol == appStorage.localCurrency })?.rate,rate > 0,
localRate > 0 {
// 其他代码
}
在这段代码的解包过程中,设置rate汇率大于0,这样可以解决除以0 的问题。
另一种是检测数值是否是有限数:
if let rate = result.filter({ $0.symbol == currency.symbol}).first?.rate, let localRate = result.first(where: { $0.symbol == appStorage.localCurrency })?.rate,rate > 0,
localRate > 0 {
let amount = currency.amount / rate * localRate
// 确保这个计算结果是正常数值(非 inf 非 nan)
if amount.isFinite {
calculateCount += amount
} else {
print("非法金额(inf 或 nan)在日期:\(date),symbol: \(currency.symbol ?? "")")
}
}
如果amount.isFinite是有限数,则为true,这里的有限数指的是,如果a为5.0,表示是有限数。如果b为Double.infinity或者Double.nan,则返回false。
通过isFinite排查不是有限数的数值,当然这两个方案可以一起使用。

总结
本次主要学习的是inf无限数和因为被除数为0导致inf无限的场景。
除了inf,还有nan(非数)的情况,在实际应用中需要考虑除以0的场景,避免同类问题的发生。