Friday, July 17, 2009

Round integer to nearest high number

This was a C language question posed on StackOverflow.com.
(Apologies in advance for the formatting - blogspot.com doesn't format VB or C or any code well - but copy and paste into Visual Studio for formatted version).

I have an array of ints like this: [32,128,1024,2048,4096]

Given a specific value, I need to get the closest value in the array that is equal to, or higher than, the value.

I have the following code

private int GetNextValidSize(int size, int[] validSizes)
{ int returnValue = size;
for (int i = 0; i < validSizes.Length; i++)
{
if (validSizes[i] >= size)
{
returnValue = validSizes[i];
break;
}
}
return returnValue;
}

It works, but is there any better/faster way to do it? The array will never contain more than 5-10 elements.

http://stackoverflow.com/questions/1143451/round-integer-to-nearest-high-number-in-array

Here's my response:


It doesn't work. Here are 3 test cases where it fails. In fact, the function interface doesn't have any return result for failure.

I wrote a corrected version, GetNextValidSize2. Since there is no way to return a failure message, I throw an exception for those cases. Here are the results of the run:

test1 : GetNextValidSize failed test1 : GetNextValidSize2 passed test2 : GetNextValidSize Object reference not set to an instance of an object. test2 : GetNextValidSize2 validSizes is nothing test3 : GetNextValidSize passed test3 : GetNextValidSize2 No items in validSizes

By the way, LINQ may be simpler or easier, but it can hardly be more efficient. It can probably be equally efficient if the query optimizer/CLR optimizer work well.

Here's the code - it's in VB since that's what I'm using at the moment, don't want to switch mental gears:

Module Module1

'''
''' Error - does not work if validSizes is Nothing, or has 0 elements, or if
''' the list contains a validSize that is not the closest one before a closer one,
''' or there are no valid sizes.
'''

Public Function GetNextValidSize(ByVal size As Integer, ByVal validSizes As List(Of Integer)) As Integer
Dim returnValue As Integer = size

For i As Integer = 0 To validSizes.Count - 1 Step 1
If validSizes.Item(i) >= size Then
returnValue = validSizes.Item(i)
Exit For
End If
Next
Return returnValue
End Function

'''
''' Returns the closest item in validSizes that is >= size. Throws an exception if one cannot
''' be found.
'''

Public Function GetNextValidSize2(ByVal size As Integer, ByVal validSizes As List(Of Integer)) As Integer
Dim closestValue As Integer = Integer.MaxValue
Dim found As Boolean = False

If validSizes Is Nothing Then
Throw New Exception("validSizes is nothing")
End If

If validSizes.Count = 0 Then
Throw New Exception("No items in validSizes")
End If

For Each x In validSizes
If x >= size Then
found = True
If x < closestValue Then
closestValue = x
End If
End If
Next
If Not found Then
Throw New Exception("No items found")
End If
Return closestValue
End Function

'''
''' Output the result of a test.
'''

Public Sub outputResult(ByVal testName As String, ByVal result As Boolean, ByVal funcName As String)
Dim passFail As String
If result Then
passFail = " passed"
Else
passFail = " failed"
End If
Console.WriteLine(testName & " : " & funcName & passFail)
End Sub

'''
''' Output the result of a test where an exception occurred.
'''

Public Sub outputResult(ByVal testName As String, ByVal ex As Exception, ByVal funcName As String)

Console.WriteLine(testName & " : " & funcName & " " & ex.Message())
End Sub

'''
''' Test with a list of 3 integers
'''

Public Sub test1()
Dim aList As New List(Of Integer)
aList.Add(5)
aList.Add(4)
aList.Add(3)
Dim result = GetNextValidSize(3, aList)
outputResult("test1", 3 = GetNextValidSize(3, aList), "GetNextValidSize")
outputResult("test1", 3 = GetNextValidSize2(3, aList), "GetNextValidSize2")
End Sub

'''
''' Test with a null reference
'''

Public Sub test2()
Dim aList = Nothing
Try
outputResult("test2", GetNextValidSize(3, aList), "GetNextValidSize")
Catch ex As Exception
outputResult("test2", ex, "GetNextValidSize")
End Try
Try
outputResult("test2", GetNextValidSize2(3, aList), "GetNextValidSize2")
Catch ex As Exception
outputResult("test2", ex, "GetNextValidSize2")
End Try
End Sub

'''
''' Test with an empty array.
'''

Public Sub test3()
Dim aList As New List(Of Integer)
Try
outputResult("test3", GetNextValidSize(3, aList), "GetNextValidSize")
Catch ex As Exception
outputResult("test3", ex, "GetNextValidSize")
End Try
Try
outputResult("test3", GetNextValidSize2(3, aList), "GetNextValidSize2")
Catch ex As Exception
outputResult("test3", ex, "GetNextValidSize2")
End Try
End Sub

'''
''' Run all tests.
'''

Public Sub testAll()
test1()
test2()
test3()
End Sub

Sub Main()
testAll()
Console.ReadLine()
End Sub

End Module

No comments:

Post a Comment