舍入崩溃的计算

时间:2016-04-02 22:33:50

标签: swift math rounding

我在我的应用程序中进行了一些计算,只有使用某些数字组合我才得到一个非常奇怪的数字:

extension Double {
    var fives: Double { return round(self * 20) / 20 }
}

let payed: Double = 97
let price: Double = 70
let tipps: Double = 48

let discount: Double = (100 - 30) / 100
let newPrice: Double = (price * discount).fives

print(newPrice - payed + tipps)

结果应打印出0.0(它在游乐场中播放),但有时在我的应用中打印出7.105427357601e-15。除了一些动画以及删除/插入一些表行之外,我没有异步做任何事情。

这"奇怪"当我不使用扩展程序fives时,行为是固定的。删除fives后,一切正常。

我知道这些信息可能不足以了解究竟发生了什么,但也许有人知道会发生什么事情?

1 个答案:

答案 0 :(得分:0)

声明:

我仍然不确定是否应该删除此帖子或将其保留为dfri指出的,因为这对我自己的个人代码来说非常具体,但仍然涵盖了之前一直被问到的主题。

解决方案:

正如dfri所指出的(以及许多其他博客/帖子),我应该尽量避免比较双打。仍然有一些情况是不可避免的(也许是我的懒惰),所以我决定将它转换为NSDecimalNumber并将其四舍五入到只有两位小数,因为这足以满足我的需要&# 34;准确性" (这根本不准确)。

使用此post我做了一个扩展程序:

var rounded: Double {
    let numbers = NSDecimalNumber(double: self)
    let handler = NSDecimalNumberHandler(roundingMode: .RoundPlain, scale: 2, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false)

    return numbers.decimalNumberByRoundingAccordingToBehavior(handler).doubleValue
}

print(0.00000001.rounded) // 0.0
print(0.00500000.rounded) // 0.01

然后我只在{I}存储值或计算属性的地方使用rounded,因此用于比较的值总是只有两位小数的精度。

可能最好的解决方案是直接使用NSDecimalNumber,但我更喜欢尽可能多地使用Swift。

我希望这个解决方案不会让我付出太多代价,但即便如此,使用该应用程序时每分钟只会调用几次。

欢迎任何关于如何改进的观点!