Obtain highest array value?

I tested three techniques to get the highest integer in an array.

  1. highest = Max( element, highest )
  2. if element > highest then highest = element
  3. highest = if( element > highest, element, highest )

Here are the results from a compiled app:

Max: 147,603 microsecs (1000000)
If: 8,950 microsecs (1000000)
Inline If: 9,225 microsecs (1000000)

It looks like my aversion to Max was justified. :slight_smile:

And if you create your own Max function that takes and returns Integers, the “Max” version drops to 30,654 microsecs.

Dim highest as integer = myArray(0)
for each element as integer in myArray()
 highest=max(highest,element)
next

should be faster yet

why create you own… one already exists

I think you missed my post with the timings above. Max is the slowest, probably (my speculation) because it takes and returns doubles so there is time to make the conversion. That’s why your own Max function that takes and returns Integers is faster.

never mind… I need to read the whole thread :slight_smile:

Here’s the fastest algorithm.

[code]Function Max(L() as Integer) As Integer
if UBound(L) = -1 then
raise new OutOfBoundsException
end if

dim maxValue as Integer = L(0)
for i as Integer = 1 to UBound(L)
if L(i) > maxValue then
maxValue = L(i)
end if
next

return maxValue
End Function[/code]

Sorting will always be slower, though on a small array the absolute time difference is negligible.

You don’t need to check for the empty array. Attempting to assign the first value to maxValue will raise the same exception if the array is empty.

Also, I doubt this is faster than using For Each since you are trading the single, redundant check of the zero element for two lookups in the array of every matching value. You could assign the value to a variable, of course, but For Each is faster at that task. (I just tested.)

For Each is a bit faster:

[code] Dim arr() As Integer

For i As Integer = 0 To 1000000
Dim r As New Random()
r.RandomizeSeed()
arr.Append(r.InRange(-999999, 999999))
Next

Dim t1ForIndex As Double = Microseconds()

Dim largestForIndex As Integer = arr(0)

Dim ub As Integer = arr.Ubound
For i As Integer = 0 To ub
Dim element As Integer = arr(i)
If element > largestForIndex Then
largestForIndex = element
End
Next

Dim t2ForIndex As Double = Microseconds()

Dim t1ForEach As Double = Microseconds()

Dim largestForEach As Integer = arr(0)

For Each element As Integer In arr
If element > largestForEach Then
largestForEach = element
End
Next

Dim t2ForEach As Double = Microseconds()

Dim t1Sort As Double = Microseconds()

arr.Sort()
Dim largestSort As Integer = arr(arr.Ubound)

Dim t2Sort As Double = Microseconds()

Dim durationForIndex As Double = (t2ForIndex - t1ForIndex) / 1000000
Dim durationForEach As Double = (t2ForEach - t1ForEach) / 1000000
Dim durationSort As Double = (t2Sort - t1Sort) / 1000000

BREAK[/code]

  1. For Each
  2. Sort
  3. For index

So have we all agreed which is the fastest - or are you guys still battling it out?
:slight_smile:

[quote=194448:@Kem Tekinay]You don’t need to check for the empty array. Attempting to assign the first value to maxValue will raise the same exception if the array is empty.

Also, I doubt this is faster than using For Each since you are trading the single, redundant check of the zero element for two lookups in the array of every matching value. You could assign the value to a variable, of course, but For Each is faster at that task. (I just tested.)[/quote]

I said that it was the fastest algorithm. Obviously there are minor optimizations specific to Xojo to be done.

Testing for an empty array makes it clear that the OutOfBoundsException is intended, and not the result of a programming error.

Update: For index is the faster than For Each and than Sort, but only when not assigning the array element to a temporary variable:

Dim ub As Integer = arr.Ubound For i As Integer = 0 To ub If arr(i) > largestForIndex Then largestForIndex = arr(i) End Next
is faster than:

Dim ub As Integer = arr.Ubound For i As Integer = 0 To ub Dim element As Integer = arr(i) If element > largestForIndex Then largestForIndex = element End Next

Update 2: removing the precomputed arr.Ubound is faster!!!

For i As Integer = 0 To arr.Ubound If arr(i) > largestForIndex Then largestForIndex = arr(i) End Next
is faster than:

Dim ub As Integer = arr.Ubound For i As Integer = 0 To ub If arr(i) > largestForIndex Then largestForIndex = arr(i) End Next

Are you testing in a compiled app or the ide?

Compiled.

Another update: Sort is the fastest solution for middle-sized arrays, for small ones (< 1000) and large ones (> 100000) For Index is still fastest.

But I am going to stop now, or I’ll have to invest the whole evening in proper benchmarking. I think I’ll better go out and have a beer or two.

I think I just blew these timings away by using a memoryblock instead of an array

Try this:

[code]
Dim arr() As Integer
dim i as integer

For i = 0 To 1000000
Dim r As New Random()
r.RandomizeSeed()
arr.Append(r.InRange(-999999, 999999))
Next

//copy the same array to a memoryblock

dim m2 as new MemoryBlock (1000001 * 4)
for i = 0 to 1000000
m2.uint32value(i) = arr(i)
next

largestForIndex = m2.uint32value(0)
Dim ub1 As Integer = 100000
For i = 0 To ub1
If m2.uint32value(i) > largestForIndex Then
largestForIndex = m2.uint32value(i)
End
Next[/code]

I thought about memory blocks too. But both the classic and the Xojo.Core one are slower, and this doesn’t include the time for copying the values to the memory block.

I think we’re going off the deep end now. :slight_smile:

Unless I timed it wrong I was seeing values of 0.08 for the baseline test, and 0.009 for using the memoryblock

I only copy from the array to the memblock so that they both had the same data.
Obviously if your source data originates in an array, it would have to be copied.
Could it originate in a memoryblock too?

My tests show 9 ms to analyze an array where Ubound = 1,000,000. Is this optimization worth the inconvenience of delving into a MemoryBlock-based array? Or is this just for fun?