1

Using stride with Swift 4 sometimes results in wrong results, what is demonstrated by this piece of code:

import UIKit
import PlaygroundSupport
struct Demo {
    let omegaMax = 10.0
    let omegaC = 1.0
    var omegaSignal:Double {get {return 0.1 * omegaC}}
    var dOmega:Double {get {return 0.1 * omegaSignal}}
    var omegaArray:[Double] {get {return Array(stride(from: 0.0, through:    omegaMax, by: dOmega))}}

The variable dOmega is expected to hold the value 0.001. The array is expected to have the size of 1001 elements, where the last element should have the value 10.0

However, these assumptions are not true, as you can see in the following code section:

let demo = Demo()
let nbrOfElements = demo.omegaArray.count
let lastElement = demo.omegaArray[nbrOfElements-1]

print("\(nbrOfElements)")  // -> 1000
print("\(lastElement)")    // -> 9.990000000000002

What is going on there? Inspecting dOmega gives the answer.

print("\(demo.dOmega)")   // -> 0.010000000000000002

The increment value dOmega is not exactly 0.01 as expected, but has a very small approximation error, which is OK for a Double. However this leads to the situation, that the expected Array element 1001 would have the value 10.000000000000002, which is bigger than the given maximum value of 10.0 and so this element 1001 is not generated. Depending whether the variables in the stride function have rounding errors or not, the result is the expected one or not.

My question is: What is the right way to use stride with Doubles to get in any case the expected result?

Heinz M.
  • 626
  • 3
  • 8

1 Answers1

1

You are using the wrong overload of stride!

There are two overloads:

You should have used the second one, because it includes the parameter through, whereas the first one does not include the parameter to.

print(Array(stride(from: 0, through: 10.0, by: 0.001)).last!) // 10.0

The little difference you see is just because of the imprecise nature of Double.

Sweeper
  • 176,635
  • 17
  • 154
  • 256
  • Sorry, there was a typo. If I use through this misbehaviour occurs. I corrected the code example. – Heinz M. Feb 16 '19 at 12:06
  • I don’t quite understand. What exactly do you want the resulting array to contain? If `Double` doesn’t work, you could just do this with `Int` and then divide each element by 1000. @HeinzM. – Sweeper Feb 16 '19 at 12:11