在Double中获得怪异的价值 [英] Getting weird value in Double

查看:69
本文介绍了在Double中获得怪异的价值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我在学习Swift时做了一个"Clicker"作为第一个项目,我有一个自动计时器,该计时器应该从其他数字中删除一些数字,但是有时我会得到0.600000000000001之类的值,而我不知道为什么.

Hello i made a "Clicker" as a first project while learning swift i have an automated timer that is supposed to remove some numbers from other numbers but sometimes i get values like 0.600000000000001 and i have no idea why.

这是我的攻击"功能,可从僵尸的生命值中移除0.2.

Here is my "Attack" function that removes 0.2 from the Health of a zombie.

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
    }

    ...
}

这是我的attackZ按钮,应该从僵尸的健康状态中删除1个

And here is my attackZ button that is supposed to remove 1 from the health of the zombie

@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
    }
}

最后是变量值:

var zHealth = 10.0
var zSize = 10.0
var pAttack = 1
var pPengar = 0
var pPengarut = 1

当计时器打开并且函数正在运行并且我单击按钮时,我有时会得到像0.600000000000001这样的怪异值,如果我将函数中的0.2设置为0.25,有时会得到0.0999999999999996.我想知道为什么会发生这种情况以及如何处理.

When the timer is on and the function is running and i click the button i sometimes get weird values like 0.600000000000001 and if i set the 0.2 in the function to 0.25 i get 0.0999999999999996 sometimes. I wonder why this happens and what to do with it.

推荐答案

trojanfoe的答案中,他共享一个链接,该链接描述了有关舍入浮点的问题的根源点号.

In trojanfoe's answer, he shares a link that describes the source of the problem regarding rounding of floating point numbers.

关于做什么,有很多方法:

In terms of what to do, there are a number of approaches:

  1. 您可以转换为整数类型.例如,如果所有现有值最多可以用两位小数表示,则将这些值乘以100,然后在各处使用Int类型,从代码中删除DoubleFloat表示形式.

  1. You can shift to integer types. For example, if your existing values can all be represented with a maximum of two decimal places, multiply those by 100 and then use Int types everywhere, excising the Double and Float representations from your code.

您可以简单地处理Double类型引入的很小的变化.例如:

You can simply deal with the very small variations that Double type introduces. For example:

  • 如果在UI中显示结果,请使用NumberFormatter使用指定的小数位数将Double值转换为String.

  • If displaying the results in the UI, use NumberFormatter to convert the Double value to a String using a specified number of decimal places.

let formatter = NumberFormatter()
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 0  // or you might use `2` here, too
formatter.numberStyle = .decimal

print(formatter.string(for: value)!)

顺便说一句,NSNumberFormatter也享有另一个好处,即它尊重用户的本地化设置.例如,如果用户居住在德国,小数位用,而不是.表示,则NSNumberFormatter将使用用户的本机数字格式.

By the way, the NSNumberFormatter enjoys another benefit, too, namely that it honors the localization settings for the user. For example, if the user lives in Germany, where the decimal place is represented with a , rather than a ., the NSNumberFormatter will use the user's native number formatting.

当测试以查看数字是否等于某个值时,而不是仅使用==运算符时,请查看两个值之间的差异,并查看它们是否在某个允许的舍入阈值之内.

When testing to see if a number is equal to some value, rather than just using == operator, look at the difference between two values and seeing if they're within some permissible rounding threshold.

您可以使用Decimal/NSDecimalNumber,在处理小数时不会出现舍入问题:

You can use Decimal/NSDecimalNumber, which doesn't suffer from rounding issues when dealing with decimals:

var value = Decimal(string: "1.0")!
value -= Decimal(string: "0.9")!
value -= Decimal(string: "0.1")!

或者:

var value = Decimal(1)
value -= Decimal(sign: .plus, exponent: -1, significand: 9)
value -= Decimal(sign: .plus, exponent: -1, significand: 1)

或者:

var value = Decimal(1)
value -= Decimal(9) / Decimal(10)
value -= Decimal(1) / Decimal(10)

请注意,我明确避免使用任何Double值,例如Decimal(0.1),因为从分数Double创建Decimal仅捕获了不精确的Double所需要的内容,而上述三个示例完全避免了这种情况.

Note, I explicitly avoid using any Double values such as Decimal(0.1) because creating a Decimal from a fractional Double only captures whatever imprecision Double entails, where as the three examples above avoid that entirely.

这篇关于在Double中获得怪异的价值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆