Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 5,939
Default Speedy code required

There are a few things that might help.
1. Change your integers to longs. Longs are actualy more efficient than
integers. Since Ints are 16bit but your system is 32 bit there is extra
overhead to using integers. Not much but a bit... The only time you want to
use an iteger is if you have an API or such requiring an integer...

2. Disable calculation. Each time you write data back to the sheet you might
be requiring the sheet to be recalculate.
Application.Calculation = xlcalculationmanual
'your code
Application.Calculation = xlcalculationautomatic

3. There are more elegant ways to deal with the arrays. Take a look at this
code to see how to get ranges into arrays and then back out to the sheet...

Sub test()
Dim rng As Range
Dim ary As Variant
Dim lng As Long

Set rng = Range("A1:A10")
ary = rng.Value

For lng = 1 To 10
'MsgBox ary(lng, 1)
Next lng

With Application
Range("B1:B10").Value = ary
End With
End Sub

Note that if you had a single dimension array you could still coerce it to 2
dimensions using application.Transpose(ary) at which point you can write it
to a range...
--
HTH...

Jim Thomlinson


"David" wrote:

My code is given below
It runs a simulation of a situation similar to a raffle draw
Each player is allocated "tickets" - ticket holdings are stored in Trng (n x
1)
Once a player "wins a prize" his remaining tickets are removed from the draw
Draw outcome is determined by comparing Rnd with remaining tickets
For each "Do" loop ranks 1 to n is allocated and stored in an n x n range
"profiles"
In this way the probabilities of outcomes for each player is arrived at
The problem is that the code is too slow for a large number of players
For example 6 hours for 100 players X 100K loops on my pc
Any ideas for speeding it up would be appreciated

Dim Trng As Range, profiles As Range
Dim r As Integer, n As Integer, place As Integer
Dim Tvals(), x As Double
Application.ScreenUpdating = False
Set Trng = Range("Trng")
n = Trng.Cells.Count
Set profiles = Trng.Offset(, 3).Resize(n, n)

ReDim Tvals(1 To n)
'\\ Save Trng values in array
For r = 1 To n
Tvals(r) = Trng.Cells(r)
Next r
profiles.ClearContents

Do
For place = 1 To n
'\\ determine Place(i)
x = Rnd * WorksheetFunction.Sum(Trng)
For Each cl In Trng
If cl < "" Then
tSum = Application.Sum(Range(Trng.Cells(1), cl))
If x < tSum Then
With Intersect(cl.EntireRow, profiles.Columns(place))
.Value = .Value + 1
End With
cl.ClearContents
Exit For
End If
End If
Next cl
Next place
'\\ re-populate Trng with original values
For r = 1 To n
Trng.Cells(r) = Tvals(r)
Next r
'\\ 100 loops for example
Loop Until Application.Sum(profiles.Columns(1)) 100



  #2   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 1,560
Default Speedy code required

Thanks Jim,
Can't wait to try your suggestions - just the sort of thing I was hoping for
I'll post back with results

"Jim Thomlinson" wrote:

There are a few things that might help.
1. Change your integers to longs. Longs are actualy more efficient than
integers. Since Ints are 16bit but your system is 32 bit there is extra
overhead to using integers. Not much but a bit... The only time you want to
use an iteger is if you have an API or such requiring an integer...

2. Disable calculation. Each time you write data back to the sheet you might
be requiring the sheet to be recalculate.
Application.Calculation = xlcalculationmanual
'your code
Application.Calculation = xlcalculationautomatic

3. There are more elegant ways to deal with the arrays. Take a look at this
code to see how to get ranges into arrays and then back out to the sheet...

Sub test()
Dim rng As Range
Dim ary As Variant
Dim lng As Long

Set rng = Range("A1:A10")
ary = rng.Value

For lng = 1 To 10
'MsgBox ary(lng, 1)
Next lng

With Application
Range("B1:B10").Value = ary
End With
End Sub

Note that if you had a single dimension array you could still coerce it to 2
dimensions using application.Transpose(ary) at which point you can write it
to a range...
--
HTH...

Jim Thomlinson


"David" wrote:

My code is given below
It runs a simulation of a situation similar to a raffle draw
Each player is allocated "tickets" - ticket holdings are stored in Trng (n x
1)
Once a player "wins a prize" his remaining tickets are removed from the draw
Draw outcome is determined by comparing Rnd with remaining tickets
For each "Do" loop ranks 1 to n is allocated and stored in an n x n range
"profiles"
In this way the probabilities of outcomes for each player is arrived at
The problem is that the code is too slow for a large number of players
For example 6 hours for 100 players X 100K loops on my pc
Any ideas for speeding it up would be appreciated

Dim Trng As Range, profiles As Range
Dim r As Integer, n As Integer, place As Integer
Dim Tvals(), x As Double
Application.ScreenUpdating = False
Set Trng = Range("Trng")
n = Trng.Cells.Count
Set profiles = Trng.Offset(, 3).Resize(n, n)

ReDim Tvals(1 To n)
'\\ Save Trng values in array
For r = 1 To n
Tvals(r) = Trng.Cells(r)
Next r
profiles.ClearContents

Do
For place = 1 To n
'\\ determine Place(i)
x = Rnd * WorksheetFunction.Sum(Trng)
For Each cl In Trng
If cl < "" Then
tSum = Application.Sum(Range(Trng.Cells(1), cl))
If x < tSum Then
With Intersect(cl.EntireRow, profiles.Columns(place))
.Value = .Value + 1
End With
cl.ClearContents
Exit For
End If
End If
Next cl
Next place
'\\ re-populate Trng with original values
For r = 1 To n
Trng.Cells(r) = Tvals(r)
Next r
'\\ 100 loops for example
Loop Until Application.Sum(profiles.Columns(1)) 100



  #3   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 1,560
Default Speedy code required

Jim,
Thanks
xlcalculationmanual saves 10% to 15 % on run time, a significant gain.
No noticable improvement with the other suggestions
Do you think that taking everytning "off sheet" using arrays would be better?


"Jim Thomlinson" wrote:

There are a few things that might help.
1. Change your integers to longs. Longs are actualy more efficient than
integers. Since Ints are 16bit but your system is 32 bit there is extra
overhead to using integers. Not much but a bit... The only time you want to
use an iteger is if you have an API or such requiring an integer...

2. Disable calculation. Each time you write data back to the sheet you might
be requiring the sheet to be recalculate.
Application.Calculation = xlcalculationmanual
'your code
Application.Calculation = xlcalculationautomatic

3. There are more elegant ways to deal with the arrays. Take a look at this
code to see how to get ranges into arrays and then back out to the sheet...

Sub test()
Dim rng As Range
Dim ary As Variant
Dim lng As Long

Set rng = Range("A1:A10")
ary = rng.Value

For lng = 1 To 10
'MsgBox ary(lng, 1)
Next lng

With Application
Range("B1:B10").Value = ary
End With
End Sub

Note that if you had a single dimension array you could still coerce it to 2
dimensions using application.Transpose(ary) at which point you can write it
to a range...
--
HTH...

Jim Thomlinson


"David" wrote:

My code is given below
It runs a simulation of a situation similar to a raffle draw
Each player is allocated "tickets" - ticket holdings are stored in Trng (n x
1)
Once a player "wins a prize" his remaining tickets are removed from the draw
Draw outcome is determined by comparing Rnd with remaining tickets
For each "Do" loop ranks 1 to n is allocated and stored in an n x n range
"profiles"
In this way the probabilities of outcomes for each player is arrived at
The problem is that the code is too slow for a large number of players
For example 6 hours for 100 players X 100K loops on my pc
Any ideas for speeding it up would be appreciated

Dim Trng As Range, profiles As Range
Dim r As Integer, n As Integer, place As Integer
Dim Tvals(), x As Double
Application.ScreenUpdating = False
Set Trng = Range("Trng")
n = Trng.Cells.Count
Set profiles = Trng.Offset(, 3).Resize(n, n)

ReDim Tvals(1 To n)
'\\ Save Trng values in array
For r = 1 To n
Tvals(r) = Trng.Cells(r)
Next r
profiles.ClearContents

Do
For place = 1 To n
'\\ determine Place(i)
x = Rnd * WorksheetFunction.Sum(Trng)
For Each cl In Trng
If cl < "" Then
tSum = Application.Sum(Range(Trng.Cells(1), cl))
If x < tSum Then
With Intersect(cl.EntireRow, profiles.Columns(place))
.Value = .Value + 1
End With
cl.ClearContents
Exit For
End If
End If
Next cl
Next place
'\\ re-populate Trng with original values
For r = 1 To n
Trng.Cells(r) = Tvals(r)
Next r
'\\ 100 loops for example
Loop Until Application.Sum(profiles.Columns(1)) 100



Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules

Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
speedy way to do array-frequency? Seeker Excel Discussion (Misc queries) 0 April 5th 09 04:03 AM
Speedy code required egun Excel Programming 1 August 22nd 08 07:49 AM
Speedy code required Joel Excel Programming 1 August 22nd 08 07:44 AM
Speedy way to create IF Function H0MELY Excel Worksheet Functions 3 February 10th 06 06:57 AM
speedy way to set values in a range emg178 Excel Programming 2 May 6th 04 08:04 PM


All times are GMT +1. The time now is 12:33 PM.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Copyright ©2004-2025 ExcelBanter.
The comments are property of their posters.
 

About Us

"It's about Microsoft Excel"