Lil*_*kaN 3 floating-point ios swift
你好,我在学习 swift 时将“Clicker”作为第一个项目我有一个自动计时器,它应该从其他数字中删除一些数字,但有时我会得到像 0.600000000000001 这样的值,我不知道为什么。
这是我的“攻击”函数,它从僵尸的生命值中移除 0.2。
let fGruppenAttackTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("fGruppenAttackTime"), userInfo: nil, repeats: true)
func fGruppenAttackTime() {
zHealth -= 0.2
if zHealth <= 0 {
zHealth = zSize
pPengar += pPengarut
}
...
}
Run Code Online (Sandbox Code Playgroud)
这是我的attackZ按钮,应该从僵尸的健康中删除 1
@IBAction func attackZ(sender: UIButton) {
zHealth -= Double(pAttack)
fHunger -= 0.05
fGruppenHunger.progress = Float(fHunger / 100)
Actionlbl.text = ""
if zHealth <= 0 {
zHealth = zSize
pPengar += pPengarut
}
}
Run Code Online (Sandbox Code Playgroud)
最后这里是变量值:
var zHealth = 10.0
var zSize = 10.0
var pAttack = 1
var pPengar = 0
var pPengarut = 1
Run Code Online (Sandbox Code Playgroud)
当计时器打开且函数正在运行时,我单击按钮有时会得到像 0.600000000000001 这样的奇怪值,如果我将函数中的 0.2 设置为 0.25,有时我会得到 0.0999999999999996。我想知道为什么会发生这种情况以及如何处理它。
在trojanfoe's answer 中,他分享了一个链接,该链接描述了有关浮点数舍入问题的根源。
至于要做什么,有多种方法:
您可以转换为整数类型。例如,如果您现有的值都可以用最多两位小数表示,请将这些值乘以 100,然后Int在任何地方使用类型,从代码中删除Double和Float表示。
您可以简单地处理Double类型引入的非常小的变化。例如:
如果在 UI 中显示结果,请使用指定的小数位数NumberFormatter将Double值转换为 a String。
let formatter = NumberFormatter()
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 0 // or you might use `2` here, too
formatter.numberStyle = .decimal
print(formatter.string(for: value)!)
Run Code Online (Sandbox Code Playgroud)
顺便说一句,它也NSNumberFormatter享有另一个好处,即它尊重用户的本地化设置。例如,如果用户居住在德国,小数位用 a,而不是 a 表示.,NSNumberFormatter则将使用用户的本地数字格式。
在测试一个数字是否等于某个值时,而不是仅使用==运算符,请查看两个值之间的差异并查看它们是否在某个允许的舍入阈值内。
您可以使用Decimal/ NSDecimalNumber,它在处理小数时不会遇到舍入问题:
var value = Decimal(string: "1.0")!
value -= Decimal(string: "0.9")!
value -= Decimal(string: "0.1")!
Run Code Online (Sandbox Code Playgroud)
或者:
var value = Decimal(1)
value -= Decimal(sign: .plus, exponent: -1, significand: 9)
value -= Decimal(sign: .plus, exponent: -1, significand: 1)
Run Code Online (Sandbox Code Playgroud)
或者:
var value = Decimal(1)
value -= Decimal(9) / Decimal(10)
value -= Decimal(1) / Decimal(10)
Run Code Online (Sandbox Code Playgroud)
请注意,我明确避免使用任何Double值,例如Decimal(0.1)因为Decimal从小数创建 aDouble只会捕获任何不精确性Double,而上面的三个示例完全避免了这种情况。
这是因为浮点舍入错误。
如需进一步阅读,请参阅每个计算机科学家应该了解的浮点运算知识。
将无限多个实数压缩为有限数量的位数需要近似表示。虽然整数有无限多个,但在大多数程序中,整数计算的结果可以存储在 32 位中。相反,给定任何固定的位数,大多数实数计算将产生无法使用这么多位数精确表示的数量。因此,浮点计算的结果通常必须进行舍入,以适应其有限表示。这种舍入误差是浮点计算的特征。
| 归档时间: |
|
| 查看次数: |
2545 次 |
| 最近记录: |