TheEliteTech
TheEliteTech

Reputation: 147

Calculating Average by Using a Function

I am trying to write a function to calculate the average in a simple math app. I am not getting any errors at all, but the code output is not showing up in the right sidebar in my Xcode playground. It outputs the two zeros in my code and stops there. Any thoughts on what's wrong?

func averageOf(numbers: Int...) -> Float {
    var sum = 0
    var numberTotal = 0

    for number in numbers {
        sum += number
        numberTotal = numbers.count
    }

    return Float(sum / numberTotal)
}

averageOf()
averageOf(10, 56, 75, 90, 109)

Upvotes: 1

Views: 5943

Answers (4)

Sherlock
Sherlock

Reputation: 1

func average(numbers: Int...) -> Float {

    var sum = 0
    var numberTotal = 0
    
    for number in numbers {
        sum += number
        numberTotal = numbers.count
    }
    return Float(sum) / Float(numberTotal)
}


average(numbers: 5, 5, 5)

// this seemed to have worked

Upvotes: 0

GoZoner
GoZoner

Reputation: 70185

Of course, except as a learning exercise, averageOf() is best implemented reusing existing functionality as:

func averageOf(_ head: Int, rest: Int...) -> Double {
  return Double (rest.reduce (head, combine: +)) / Double (1 + rest.count)
}
27> averageOf (1, 2, 3)
$R6: Double = 2

The above avoids the 'how do you average no numbers' problem by requiring one argument. You also will want to be careful about your division use:

 33> Double (3/2)
$R9: Double = 1
 34> Double(3)/Double(2)
$R10: Double = 1.5

Also, the usefulness of optional arguments created with ... is limited until there is an apply() function like

   var theAverage = apply (averageOf, someGiantArrayOfInts)

Upvotes: 3

FreeNickname
FreeNickname

Reputation: 7814

When you call averageOf(), it seems to cause the playground to crash (division by zero, because numberTotal is 0). For instance, if you called it like this:

averageOf(10, 56, 75, 90, 109)
averageOf(10, 20, 30)
averageOf()
averageOf(10, 20, 30)

you would get an output for the first two calls, but not for the second two.

UPDATE 3 (credits to @wumm) If you clicked on any of variables on the right panels or opened an assistant editor , you would see the error (rather strange one, though):

Playground execution failed: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
* thread #1: tid = 0x1c4a02, 0x000000010aff7e14, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  * frame #0: 0x000000010aff7e14

The solution is to check numberTotal in the end. And, by the way, there is no need to assign it inside the loop :) Here is a fixed version:

UPDATE: cheching numberTotal in the beginning is more reasonable indeed (credits to @kovpas): UPDATE 2: changed the return part. Credits to `@MartinR.

func averageOf(numbers: Int...) -> Float {
    var numberTotal = numbers.count
    if numberTotal == 0 {
        return 0
    }
    var sum = 0

    for number in numbers {
        sum += number
    }
    return Float(sum)/Float(numberTotal)
}

averageOf(10, 56, 75, 90, 109)
averageOf(10, 20, 30)
averageOf()
averageOf(10, 20, 30)

Upvotes: 3

kovpas
kovpas

Reputation: 9593

You should first check if your array contains numbers. Otherwise you divide by 0.

func averageOf(numbers: Int...) -> Float {
    if numbers.count == 0 {
        return 0
    }

    var sum = 0

    for number in numbers {
        sum += number
    }

    return Float(sum / numbers.count)
}

Upvotes: 1

Related Questions