Nicola Prada - 1 year ago 123

Swift Question

I need to round stocks, indices and futures prices to the nearest tick. The first step is to look if the price is a multiple of the tick. Apple docs says "*Unlike the remainder operator in C and Objective-C, Swiftâ€™s remainder operator can also operate on floating-point numbers*".

If I write the following code in a playground or in a console app and I run it, I expect **0** as result but I get a remainder value equals to **0.00999999999999775**:

`var stringPrice = "17.66"`

var price = Double(stringPrice)

var tickSize: Double = 0.01

let remainder = price! % ticksize

This problem breaks my rounding function when using values such 17.66 as aPrice and 0.01 as aTickSize:

`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

}

What is the best way to fix this?

Recommended for you: Get network issues from **WhatsUp Gold**. **Not end users.**

Answer Source

Following the comments about the broken floating point math and the need to avoid floats and doubles for all the operations concerning money I changed my code to perform the remainder operation using NSDecimalNumbers. This seems to solve the precision problem.

```
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)")
```

Recommended from our users: **Dynamic Network Monitoring from WhatsUp Gold from IPSwitch**. ** Free Download**