7
$\begingroup$

My task is simple.

Calculate the average value for 10^7 dice throws using computer pseudo-random-number-generator.

x := RandomInteger[{1, 6}] 

gives me one random value.

xn[n_] := 1/n Sum[x, {j, 1, n}] 

gives me the average value for n throws.

If I set n = 10^6 its just fine and I get a number around 3.5, but as soon as I set n = 10^7, I get an integer between 1 and 6 with a dot after it, which means that Mathematica rounds the result, right?. The problem is, that Mathematica doesnt even start calculating those 10^7 values.

Of course, I could just sum 10 times xn[10^6] and divide it by 10, but I want it to work with n = 10^7 right away.

$\endgroup$
  • $\begingroup$ You can format inline code and code blocks by selecting the code and clicking the {} button above the edit window. The edit window help button ? is useful for learning how to format your questions and answers. You may also find this meta Q&A helpful $\endgroup$ – Michael E2 Oct 21 '17 at 23:46
  • $\begingroup$ When trying ${10}^{7}$ values, was it actually returning integers like 1? Curious mostly because getting an average of $1$, or even something that rounds to $1$, after ${10}^{7}$ dice throws is absurdly unlikely, so it'd be weird if Mathematica's logic allowed for that result to be returned, even under some sort of approximation logic. $\endgroup$ – Nat Oct 23 '17 at 2:31
6
$\begingroup$

Sum is, at its core, a symbolic method intended to deduce sums of large, perhaps infinite series. To actually add up numbers, use Total.

xn[n_] := 1/n Total[Table[x, {j, 1, n}]]
xn[10^8]
349988177/100000000
$\endgroup$
  • $\begingroup$ Thanks! Worked. $\endgroup$ – S. Den Oct 21 '17 at 22:15
  • 2
    $\begingroup$ a faster solution in the same spirit would be xn[n_] := ConstantArray[1, n].RandomInteger[{1, 6}, n]/n $\endgroup$ – M. Stern Oct 22 '17 at 1:51
  • $\begingroup$ Why not use Mean[]? $\endgroup$ – J. M. will be back soon Oct 26 '17 at 13:29
  • $\begingroup$ @J. M. For toy problems like this, I try to focus on solving the key issue with minimal change. In this case, the key was replacing Sum with something guaranteed to add up numbers rather than trying some more analytic method. Further optimization might be a distraction. But yes, RandomInteger can create the whole list in one go, and Mean avoids a division. $\endgroup$ – John Doty Oct 26 '17 at 22:48
9
$\begingroup$

There is a system option:

SystemOptions["SymbolicSumThreshold"]
(*  {"SymbolicSumThreshold" -> 1000000}  *)

Above a sum of length 10^6, Sum will try a symbolic method. I'm not sure it's worth trying to explain why a symbolic method will fail on a random summand.

Some alternatives:

xn[n_] := With[{opts = SystemOptions["SymbolicSumThreshold"]},
   Internal`WithLocalSettings[
    SetSystemOptions[{"SymbolicSumThreshold" -> n}],
    1/n Sum[x, {j, 1, n}],
    SetSystemOptions[opts]
    ]
   ];

xn[n_] := 1/n Sum[x, {j, 1, n}, Method -> "Procedural"];

xn[n_] := 1/n Total@RandomInteger[{1, 6}, n];   (* bypasses  x  *)

The last one will be fastest, probably the fastest possible.

$\endgroup$
  • 2
    $\begingroup$ Actually, I have a guess about the random summand: It appears as x, Sum assumes it's a constant, and n*x is returned. Somewhere in the process, x is evaluated and a random integer between 1 and 6 is the result. $\endgroup$ – Michael E2 Oct 22 '17 at 1:49
  • $\begingroup$ No need to guess: Count[#, _RandomInteger, Infinity] & /@ {xn[10^6] // Trace, xn[10^6 + 1] // Trace, xn[10^7] // Trace} You are right, for the symbolic evaluation x is evaluated only once. $\endgroup$ – Karsten 7. Oct 22 '17 at 19:39
6
$\begingroup$

A better way to define xn is

xn[n_Integer /; Positive[n]] := Mean[RandomInteger[6, n]]

This definition requires n to be a positive integer, which is a reasonable constraint for this problem.

Let's look at some evaluations. I useSeedRandom to get reproducible results.

SeedRandom[42]; Table[xn[i], {i, 0, 5}]

{xn[0], 3, 5/2, 4/3, 9/4, 13/5}

Note that zero is not accepted and that the results are all exact numbers.

Now lets look at n = 10^7.

SeedRandom[42]; x10to7 = xn[10^7]

5999573/2000000

x10to7 // N  // InputForm

2.9997865

In this case, the machine value contains an accurate representation of the exact number.

2.9997865`100 - x10to7

0.*10^-100

$\endgroup$
1
$\begingroup$

RandomInteger[{1, 6}] is not a 'pure' function. Surely what is happening here is that you're confusing its symbolic calculations.

I presume the following is what's happening:

  • When you sum $10^6$ terms, the implementation says "Oh, I can just compute all the terms and add them up" rather than doing any symbolic manipulation of the summation, and thus evaluates the RandomInteger function for every term.
  • When you sum $10^7$ terms, the implementation says "Oh, that's a lot; I'll do symbolic manipulation". It sees that the formula being summed does not involve j or n in any fashion, and infers it to be a constant, and thus Sum[x, {j, 1, n}] gets simplified to x n, and thus evaluates RandomInteger only once.
$\endgroup$
0
$\begingroup$

I just got it working, by using the numerical value for every summand: xn[n_] := Sum[N[x/n], {j, 1, n}]

Still I would like to know, why my first solution didnt work at high numbers, but at lower ones...

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.