我需要把股票、指数和期货价格四舍五入到最接近的刻度。第一步是看价格是否是价格的倍数。苹果文档称“与C和Objective-C中的余数运算符不同,Swift的余数运算符也可以对浮点数进行操作”。
如果我在操场或控制台应用程序中编写以下代码并运行它,则结果会是0,但余数值等于0.009999999999775:

var stringPrice = "17.66"
var price = Double(stringPrice)
var tickSize: Double = 0.01

let remainder = price! % ticksize

当使用aPrice等17.66和aTickSize等0.01值时,此问题破坏了我的舍入函数:
func roundPriceToNearestTick(Price aPrice: Double, TickSize a TickSize: Double)-> Double{
    let remainder = aPrice % aTickSize
    let shouldRoundUp = remainder >= aTickSize/2 ? true : false
    let multiple = floor(aPrice/aTickSize)
    let returnPrice = !shouldRoundUp ? aTickSize*multiple : aTickSize*multiple + aTickSize
    return returnPrice
}

解决这个问题的最好方法是什么?

最佳答案

在对断开的浮点数学和所有与金钱有关的操作都需要避免浮点数和双倍数的评论之后,我更改了代码以使用NSDecimalNumbers执行余数操作。这似乎解决了精度问题。

var stringPrice = "17.66"
var tickSizeDouble : Double = 0.01
var tickSizeDecimalNumber: NSDecimalNumber = 0.01

func decimalNumberRemainder(Dividend aDividend: NSDecimalNumber, Divisor aDivisor: NSDecimalNumber)->NSDecimalNumber{

    let behaviour = NSDecimalNumberHandler(roundingMode: NSRoundingMode.RoundDown,
                                                  scale: 0,
                                       raiseOnExactness: false ,
                                        raiseOnOverflow: false,
                                       raiseOnUnderflow: false,
                                    raiseOnDivideByZero: false )

    let quotient = aDividend.decimalNumberByDividingBy(aDivisor, withBehavior: behaviour)
    let subtractAmount = quotient.decimalNumberByMultiplyingBy(aDivisor)
    let remainder = aDividend.decimalNumberBySubtracting(subtractAmount)
    return remainder
}


let doubleRemainder = Double(stringPrice)! % tickSizeDouble
let decimalRemainder = decimalNumberRemainder(Dividend: NSDecimalNumber(string: stringPrice), Divisor:tickSizeDecimalNumber)


print("Using Double: \(doubleRemainder)")
print("Using NSDecimalNumber: \(decimalRemainder)")

关于swift - Swift余数运算符精度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38261876/

10-09 06:35