2015-09-23 54 views
1

你好,我做了一個「點擊」作爲第一個項目,同時學習迅疾我有一個應該是從其他數字刪除一些數字,但有時我得到這樣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 
    } 

    ... 
} 

這裏是我的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 
    } 
} 

最後這裏的變量值:

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有點ES。我想知道爲什麼會發生這種情況以及如何處理它。

回答

2

trojanfoe's answer,他shares a link描述了關於浮點數四捨五入問題的來源。

在做什麼方面,有許多方法:

  1. 可以轉移到整數類型。例如,如果您現有的值都可以,每次最多兩位小數來表示,這些乘以100,然後用Int類型無處不在,從你的代碼切除DoubleFloat表示。

  2. 你可以簡單的處理非常小的變化是Double類型介紹。例如:

    • 如果顯示在用戶界面中的效果,請使用NumberFormatter使用小數指定數量的Double值到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)!) 
      

      順便說一句,在NSNumberFormatter享有另外一個好處,也即它榮譽用戶的本地化設置。例如,如果用戶居住在德國,其中小數位的位置是,而非.,則NSNumberFormatter將使用用戶的本機號碼格式。

    • 當測試數字是否等於某個值時,而不是僅使用==運算符,查看兩個值之間的差異並查看它們是否在某個允許的舍入閾值內。

  3. 您可以使用Decimal/NSDecimalNumber,帶有小數處理時不會從四捨五入問題的影響:

    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),因爲創建Decimal來自分數Double僅捕獲任何不精確Double需要,其中上述三個示例完全避免。

+0

NSDecimalNumber沒有雙重目前(它的特點是「十進制」或「值」) –

+1

是啊,我們甚至不應該使用'NSDecimalNumber'了,反正。我們使用'Decimal'。我也更新了Swift 3及更高版本的'NumberFormatter'示例。 – Rob

+0

我必須承認我今天使用了NSDecimalNumber,它給出了同樣奇怪的問題。我現在必須嘗試Decimal :-) –

3

這是因爲浮點舍入錯誤。

如需進一步閱讀,請What Every Computer Scientist Should Know About Floating-Point Arithmetic

將無限多個實數擠壓成有限位數 需要近似表示法。雖然無限多個整數,但在大多數程序中,整數計算的結果可以以32位存儲。相比之下,給定任意固定位數,大多數使用實數的計算將產生不能使用那麼多位精確表示的數量。因此,浮點計算的結果必須經常按照 的順序進行四捨五入以適應其有限表示。該四捨五入錯誤是浮點計算的特徵 。