1

I have tried to update a little function to Swift 2.1. The original working code was:

import func Darwin.sqrt
func sqrt(x:Int) -> Int { return Int(sqrt(Double(x))) }

func sigma(n: Int) -> Int {
    // adding up proper divisors from 1 to sqrt(n) by trial divison
    if n == 1 { return 0 } // definition of aliquot sum
    var result = 1
    let root = sqrt(n)
    for var div = 2; div <= root; ++div {
        if n % div == 0 {
            result += div + n/div
        }
    }
    if root*root == n { result -= root }
    return (result)
}
print(sigma(10))
print(sigma(3))

After updating the for loop I get a runtime error for the last line. Any idea why that happens?

import func Darwin.sqrt
func sqrt(x:Int) -> Int { return Int(sqrt(Double(x))) }

func sigma(n: Int) -> Int {
    // adding up proper divisors from 1 to sqrt(n) by trial divison
    if n == 1 { return 0 } // definition of aliquot sum
    var result = 1
    let root = sqrt(n)
    for div in 2...root where n % div == 0 {
            result += div + n/div
    }
    if root*root == n { result -= root }
    return (result)
}
print(sigma(10))
print(sigma(3)) //<- run time error with for in loop
3
  • Since you are updating your code, you might want to change if n == 1 {return 0} to guard n != 1 else { return 0 } Commented Jan 8, 2016 at 11:13
  • Using stride() is another option, compare stackoverflow.com/questions/34323227/…. Commented Jan 8, 2016 at 11:33
  • @ramkrishna-sharma Don't tag with "ios" questions that are not directly related to iOS. Swift is also supported by OS X and now Linux; Swift questions may apply and are not specific to iOS. In short: Swift ≠ iOS. Thank you. Commented Jan 8, 2016 at 11:36

1 Answer 1

6

When you pass 3 to sigma, your range 2...root becomes invalid, because the left side, the root, is less than the right side, 2.

The closed range operator (a...b) defines a range that runs from a to b, and includes the values a and b. The value of a must not be greater than b.

root is assigned sqrt(n), which means that in order for the 2...root range to remain valid, n must be above 22.

You can fix by supplying a lower limit for the right side, i.e.

for div in 2...max(root,2) where n % div == 0 {
    ...
}

However, at this point your solution with the regular for loop is more readable.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your fast answer. I did expect that the for-in-loop would not be executed at all. Fixing the upper bounds by finding the maximum of upper and lower bounds is semantically different. I will follow your advice and keep the regular for loop.
@Tiza However, note that the regular C-style loop will get removed from Swift in Swift 3.0 so if you rewrite it now, it will save you time later. See github.com/apple/swift-evolution/blob/master/proposals/… You might want to use another for loop variant or a while loop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.