views:

91

answers:

3

Hi All,

The following code takes a timeframe in minutes since midnight and creates an array with minutes pr hour. But, it's slow. Any better suggestions out there? (no, changing language is not an option :-) )

Const clDeparture   As Long = 123
Const clArrival     As Long = 233
Dim lHour           As Long
Dim lMinute         As Long
Dim alHour(25)      As Long

For lMinute = 0 To 1440
    If lMinute >= clDeparture And lMinute < clArrival Then
        alHour(Int(lMinute / 60)) = alHour(Int(lMinute / 60)) + 1
    End If
Next

The array should now contain:

(0,0) (1,0) (2,57) (3,53) (4,0) .....

Regards

+1  A: 

Well, how about:

For lMinute = clDeparture To clArrival - 1
    alHour(Int(lMinute / 60)) = alHour(Int(lMinute / 60)) + 1
Next

Given that you're only going to be taking any actions for minutes between clDeparture and clArrival, there's no point in looping through the rest of them.

That's a simple start. You could certainly improve it by looking through each hour instead of each minute and checking what proportion of that time was "covered" by the time period. That would be trickier, but certainly doable. I wouldn't want to venture to code that in VB, but I could probably whip up a C# version if you really wanted. I'd start off with the simple code and see if that's fast enough though.

Jon Skeet
hehe, thanks, that cut the time by 60%. But still, there must be a way to do this pr hour?
hey, if you could do a C# version then i could probably convert it to VB, it's just the basic math around this issue that i have problems with
@corger: I'll see if I can find the time later on. Just to check, you really do want it to be *inclusive* of `clDeparture` and *exclusive* of `clArrival`, right?
Jon Skeet
right, i started out with trying to do this per hour and just gave up and did it the simplest way i could think of. So, yes, between clDeparture and clArrival.
A: 

You want to know how many minutes of each hour are in the time span?
I think this should do it, or something close to it:

lDepHour = Int(clDeparture / 60)
lDepMinute = clDeparture - lDepHour * 60
lArrHour = Int(clArrival / 60)
lArrMinute = clArrival - lArrHour * 60

If (lDepHour = lArrHour) Then
  alHour(lDepHour) = lArrMinute - lDepMinute
Else
  alHour(lDepHour) = 60 - lDepMinute
  alHour(lArrHour) = lArrMinute
  For lHour = lDepHour + 1 To lArrHour - 1
    alHour(lHour) = 60
  End For
End If

This should be about 60 times faster than what you've got.

P.S. If the time span can span midnight (arrival < departure) then add 24*60 to the arrival time, do the same logic, and if lHour >= 24, put the numbers in lHour - 24.

Mike Dunlavey
Perfect, this is what I was looking for, thanks!, btw, the 1mill test went from 63 seconds to 297 milliseconds :-)
@corger: Sounds about right. Awesome.
Mike Dunlavey
A: 

Use integer arithmetic instead of floating point:

Int(lMinute / 60)

is the same as

lMinute \ 60

But the latter is faster because it uses integer division and saves the need to convert from Long to Double and back. Furthermore, VB6 doesn’t optimize well. If you need the value twice, consider storing the result in a variable.

Konrad Rudolph
Nix, not the same, wrapping it with Int() will only return the integer part... Without it rounding will occur and the minutes ends up on the wrong hour. Storing the result in a variable is a good idea though.
@corger: It **is** the same: Notice that the second code uses a backslash: that’s an **integer division**. The *same* rounding goes on in both codes: both results are always rounded towards zero.
Konrad Rudolph
urgh, didn't notice the backslash, I stand corrected