MathGroup Archive 2005

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: For Loop and Array related

  • To: mathgroup at smc.vnet.net
  • Subject: [mg58031] Re: For Loop and Array related
  • From: Maxim <ab_def at prontomail.com>
  • Date: Thu, 16 Jun 2005 05:37:59 -0400 (EDT)
  • References: <d8oucl$t6q$1@smc.vnet.net>
  • Sender: owner-wri-mathgroup at wolfram.com

On Wed, 15 Jun 2005 10:03:01 +0000 (UTC), mchangun at gmail.com  
<mchangun at gmail.com> wrote:

> Hi All,
>
> I have an array with 100 elements, all set to zero initially.  Then I
> want to randomly choose one element and increase its value by one, and
> repeat this 16000 times. Here is my code:
>
> Lattice = Table[0, {n, 100}];
> For[i = 1, i = 16000, i++, Lattice[[Random[Integer, {1, 100}]]]++]
>
> So now if I add all the elements in the list Lattice together, I should
> get 16000 (I use Total[Lattice] to get the sum of the list).  But this
> doesn't happen, and strangely, each time I run this, the sum of the
> list is different!  What am I doing wrong?
>
> Also I'm aware that a lot of Mathematica newbies try and write code
> like it were C++ and I think i've fallen into this trap as well.  So is
> there a different (more Mathematica) way which I can implement the
> above?
>
> Thanks in advanced.
>

Increment[x] internally evaluates x = x + 1 (and returns the old value of  
x then). Therefore, L[[Random[...]]]++ becomes L[[Random[...]]] =  
L[[Random[...]]] + 1, where Random is evaluated twice and gives two  
different indices.

Perhaps it would be better if Increment, AddTo and other assignment  
functions evaluated the arguments of the left-hand side once; that is, in  
pos=1;L[[pos++]]++ the argument pos++ should be evaluated once and then  
the expression should be transformed into L[[1]] = L[[1]] + 1. This way we  
get the desired behaviour: pos now has the value 2 and the first element  
of L is incremented. Otherwise Increment just confuses the programmer into  
thinking that it will work like in C. This still wouldn't get rid of side  
effects, though, as x = x + 1 still evaluates x on the right-hand side of  
Set.

Your example can be rewritten as

Lattice[[#]]++& /@ Table[Random[Integer, {1, 100}], {16000}]

For further speed-up, this can be compiled:

Lattice = Compile[{},
   Module[{Lattice},
     Lattice = Table[0, {100}];
     Lattice[[#]]++& /@ Table[Random[Integer, {1, 100}], {16000}];
     Lattice
]][];

Sow and Reap give comparable performance:

Lattice = Last@ Reap[
   Sow[0, Range@ 100];
   Sow[0, Table[Random[Integer, {1, 100}], {16000}]],
   _, Length@ #2 - 1&];

If the number of tries is much larger than 16000, then the compiled  
version takes several times less memory than uncompiled, most likely due  
to the use of packed arrays.

Maxim Rytin
m.r at inbox.ru


  • Prev by Date: Re: For Loop and Array related
  • Next by Date: Re: problem with InverseLaplaceTransform
  • Previous by thread: Re: For Loop and Array related
  • Next by thread: Re: For Loop and Array related