tanker405th
tanker405th

Reputation: 21

Need VB Do...While loop to calculate average

Coding newbie. I had a project last week that required user input of 4 grades, and then calculating the average of all 4 grades, and the average with the lowest grade dropped (already turned in btw). Requirements were a For Next loop and a Do While loop to calculate the averages. I used the For Next loop to get the total of the 4 grades and then calculated average.

    Declare variables, constant, and array
        Const intMAX_SUBSCRIPT As Integer = 3 
        Dim intGrades(intMAX_SUBSCRIPT) As Integer 
        Dim intTotal As Integer = 0     'holds the total of grades
        Dim dblAverage As Double        'holds the average of all 4 grades
        Dim intCount As Integer         'loop counter
        Dim intLowest As Integer        'holds the lowest score

        'assign grades to array slots
        intGrades(0) = CInt(txtGrade1.Text)
        intGrades(1) = CInt(txtGrade2.Text)
        intGrades(2) = CInt(txtGrade3.Text)
        intGrades(3) = CInt(txtGrade4.Text)

        'Loop to calculate average in grades array
        'get total of all grades
        For intCount = 0 To (intGrades.Length - 1)
            intTotal += intGrades(intCount)

        Next
        'use floating-point div to find average
        dblAverage = intTotal / intGrades.Length

This worked as it should. I then used the following to find the lowest grade:

        intLowest = intGrades(0)

        'Search for the lowest grade in the array
        For intCount = 1 To (intGrades.Length - 1)
            If intGrades(intCount) < intLowest Then
                intLowest = intGrades(intCount)
            End If
        Next

This too worked as it should. Now for the problem I had: getting a Do While to calculate the new average with the lowest score dropped. This is where I need help:

        Dim intNewTotal As Integer = 0  'holds the new total of the 3 highest grades
        Dim dblNewAverage As Double 'holds the new average with the lowest score dropped
        Dim intNewCount As Integer = 0 'loop counter 

        Do While intNewTotal <= (intTotal - intLowest)
            intNewTotal = intNewTotal + intGrades.Length - 1
            intNewCount += 1
        Loop

        dblNewAverage = intNewTotal / 3

The math is close, but not quite. With grades of 100, 100, 80, and 100 I get the following results: Average of all 4 = 95, Average with lowest score dropped = 101. The new average is always one higher than it should be. What can I do to fix this? I really want to understand so that I can fix this problem if it happens again. Thanks!

Upvotes: 1

Views: 3840

Answers (3)

The_Black_Smurf
The_Black_Smurf

Reputation: 5269

The problem is with this line of code:

intNewTotal = intNewTotal + intGrades.Length - 1

Instead of adding the grade value, you add the length of the intGrades array until you reach the Do while condition: intNewTotal <= (intTotal - intLowest)

I understand your question is for academic purpose so if you really need to use a Do While loop to calculate the average, I would use it that way (untested):

Dim index As Int = 0
Do While index <= intMAX_SUBSCRIPT  

  If (intGrades(index) <= intLowest) Then
    intNewTotal += intGrades(index)
    intNewCount += 1    
  End if

  index += 1

Loop

dblNewAverage = intNewTotal / intNewCount

Edit

Dropping the lowest grade may be interpreted 2 different way. If you have values 80, 80, 100, 110 you may want to drop only one of the 80 value, or both of them. My code above is dropping both of them. If you want to remove only one of them, then your should set the starting index to 1 to skip the first item and remove the if condition:

Dim index As Int = 1
Do While index <= intMAX_SUBSCRIPT  
    intNewTotal += intGrades(index)
    index += 1
Loop

dblNewAverage = intNewTotal / (intGrades.Length - 1)

Upvotes: 1

PT_01
PT_01

Reputation: 156

Dim j As New List(Of Int32)
    Dim sum As Int32 = 0
    For i = 1 To 4 '4 number of textboxes
        j.Add(CType(Controls.Item("txtGrade" + i.ToString), TextBox).Text)
        sum += Val(CType(Controls.Item("txtGrade" + i.ToString), TextBox).Text)
    Next
    j.Sort()
    Dim intLowest As Int32 = j(0)
    Dim avg As Int32 = sum / j.Count

Upvotes: 0

Joel Coehoorn
Joel Coehoorn

Reputation: 415665

This may be homework, in which case you won't understand any of this anyway. But if you're actually trying to learn how a pro would do it, the code would look more like this:

Dim Grades As New List(Of Integer) From {CInt(txtGrade1.Text), CInt(txtGrade2.Text), CInt(txtGrade3.Text), CInt(txtGrade4.Text)} 

Dim Total As Integer = Grades.Sum()
Dim Average As Double = Grades.Average()       'holds the average of all 4 grades
Dim Lowest As Integer = Grades.Min()      'holds the lowest score
Dim NewAverage As Double = CDbl(Total - Lowest) / (Grades.Count - 1)

And drop the silly type prefixes on your variable names. They used to be popular and made sense back before Option Strict was the default, but now even Microsoft's own style guidelines recommend against them.

Upvotes: 1

Related Questions