【问题标题】:Swifts stride with Doubles is unreliable斯威夫特与双打的步伐是不可靠的
【发布时间】:2019-02-16 09:56:23
【问题描述】:

在 Swift 4 中使用 stride 有时会导致错误的结果,这段代码证明了这一点:

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))}}

变量 dOmega 预计保持值 0.001。 该数组预计有 1001 个元素的大小, 其中最后一个元素的值应为 10.0

但是,这些假设并不正确,您可以在以下代码部分中看到:

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

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

那里发生了什么?检查 dOmega 给出了答案。

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

增量值 dOmega 并不像预期的那样精确为 0.01,但具有非常小的近似误差,这对于 Double 来说是可以的。然而,这会导致这样的情况,即预期的数组元素 1001 将具有值 10.000000000000002,该值大于给定的最大值 10.0,因此不会生成此元素 1001。 根据 stride 函数中的变量是否存在舍入误差,结果是否为预期值。

我的问题是:在任何情况下,使用双精度步长来获得预期结果的正确方法是什么?

【问题讨论】:

标签: swift stride


【解决方案1】:

您使用了错误的 stride 重载!

有两个重载:

您应该使用第二个,因为它包含参数through,而第一个不包含参数to

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

您看到的细微差别仅仅是因为imprecise nature of Double

【讨论】:

  • 对不起,有一个错字。如果我使用通过这种不当行为发生。我更正了代码示例。
  • 我不太明白。您究竟希望结果数组包含什么?如果 Double 不起作用,您可以使用 Int 执行此操作,然后将每个元素除以 1000。@HeinzM。
猜你喜欢
  • 2017-07-22
  • 2017-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-20
  • 1970-01-01
  • 2020-08-01
  • 2016-02-08
相关资源
最近更新 更多