为什么我的Swift循环失败并显示错误"无法在结束<start时形成范围"?

lag*_*oon 28 for-loop runtime-error factors swift

我有一个for循环,它检查一个数字是否是一个数字的因子,然后检查该因子是否为素数,然后将它添加到数组.根据原始号码,我会收到错误消息

致命错误:无法使用end <start形成范围

这几乎每次都会发生,但对于某些数字,它可以正常工作.我发现使用它的唯一数字是9,15和25.

这是代码:

let num = 16 // or any Int
var primes = [Int]()

for i in 2...(num/2) {

    if ((num % i) == 0) {
        var isPrimeFactor = true

        for l in 2...i-1 {
            if ((i%l) == 0) {
                isPrimeFactor = false;
            }//end if
        }//end for

        if (isPrimeFactor == true) {
            primes.append(i)
        }//end if

    }//end if

}//end for
Run Code Online (Sandbox Code Playgroud)

nah*_*g89 41

如果你需要一个具有动态值范围的循环,我建议使用stride(to:by:)而不是..<...

基本上..<...将要崩溃,如果start_index > end_index.

例如:

let k = 5
for i in 10...k { print("i=\(i)") }
for i in 10..<k { print("i=\(i)") }
Run Code Online (Sandbox Code Playgroud)

怎么修:

// swift 2.3
let k = 5
for i in 10.stride(to: k+1, by: 1) { print("i=\(i)") }
for i in 10.stride(to: k, by: 1) { print("i=\(i)") }

// swift 3.0
let k = 5
for i in stride(from: 10, through: k, by: 1) { print("i=\(i)") }
for i in stride(from: 10, to: k, by: 1) { print("i=\(i)") }
Run Code Online (Sandbox Code Playgroud)

注意:上面的2个块不会打印任何内容,但其中一个块在执行时崩溃.如果要从较高的数字跨越到较低的数字,则by需要将参数更改为负数.

参考:

  • "by"参数必须为(-1)或不打印任何内容 (6认同)
  • @igrrik:请仔细阅读。我们正在讨论由 ..&lt; 导致的致命错误以及如何修复它。分别运行上面的两个块代码,你会看到。 (2认同)

chr*_*ris 9

在你的第二个循环中,i总是从2开始,这意味着你正在循环2...1

  • 这三个数字都是奇数,所以`num%i`条件是假的. (2认同)
  • 在任何普通的编程语言中,你编写 `for(...;lowerBound&lt;upperBound;...)` 进入循环时条件为假,整个循环通过。这种情况是绝对正常的。但是 swift 太愚蠢了,无法理解它,您需要额外的条件和/或其他循环语法 (2认同)

Wis*_*ssa 5

斯威夫特 4

最好的方法是使用本文档页面中的strideGeneric Function stride(from:to:by:)

for i in stride(from: 10, through: 5, by: -1) { print(i) }

如果要包含lowerBound,则跨步:通用函数跨步(from:through:by :)


Bry*_*ner 5

双方ClosedRangeCountableRange抛出这个错误,除非start <= end。使用的一个问题stride(from:to:by)是它返回 aStrideable而不是 a Range,这不适用于“在范围内”运算符~=。为了处理这些情况,我使用了一个扩展,它为我提供了一个边界安全范围,其中无效范围变为空范围:

extension Int {
  func until(_ end: Int) -> CountableRange<Int> {
    return self <= end ? self..<end : self..<self
  }

  func through(_ end: Int) -> CountableRange<Int> {
    return self <= end ? self..<(end + 1) : self..<self
  }
}
Run Code Online (Sandbox Code Playgroud)

两者都返回CountableRange以使无效through范围变为空范围。(旁注:until选择这个名称是因为这个“安全”范围的行为与untilKotlin/Android 中的范围相同)。

用法:

for i in 0.until(3) { /* do something */ }

let printRange = { (range: Range<Int>) -> Void in
  for i in range {
    print(i, terminator: " ")
  }
  print()
}
printRange(0.until(3))  // prints "0 1 2"
printRange(0.until(0))  // prints ""
printRange(3.until(0))  // prints ""
printRange(0.through(3))  // prints "0 1 2 3"
printRange(0.through(0))  // prints "0"
printRange(3.through(0))  // prints ""
print(0.until(1) ~= -1)  // prints "false"
print(0.until(1) ~= 0)  // prints "true"
print(0.until(1) ~= 1)  // prints "false"
print(0.until(0) ~= 0)  // prints "false"
print(1.until(0) ~= 0)  // prints "false"
print(0.through(1) ~= -1)  // prints "false"
print(0.through(1) ~= 0)  // prints "true"
print(0.through(1) ~= 1)  // prints "true"
print(0.through(0) ~= 0)  // prints "true"
print(1.through(0) ~= 0)  // prints "false"
Run Code Online (Sandbox Code Playgroud)