More efficient simluation of 2 dice rolls - Python -


i wrote program records how many times 2 fair dice need rolled match probabilities each result should expect.

i think works i'm wondering if there's more resource friendly way solve problem.

 import random   expected = [0.0, 0.0, 0.028, 0.056, 0.083,               0.111, 0.139, 0.167, 0.139, 0.111,              0.083, 0.056, 0.028]   results = [0.0] * 13  # store our empirical results here   emp_percent = [0.0] * 13  # results / count   count = 0.0  # how many times have rolled dice?    while true:      r = random.randrange(1,7) + random.randrange(1,7)  # roll our die      count += 1       results[r] += 1      emp_percent = results[:]       in range(len(emp_percent)):          emp_percent[i] /= count          emp_percent[i] = round(emp_percent[i], 3)       if emp_percent == expected:          break  print(count) print(emp_percent) 

there several problems here.

firstly, there no guarantee ever terminate, nor particularly terminate in reasonable amount of time. ignoring floating point arithmetic issues, should terminate when numbers distributed exactly right. law of large numbers not guarantee ever happen. law of large numbers works this:

  1. your initial results (by random chance) biased 1 way or another.
  2. eventually, trials not yet performed outnumber initial trials, , lack of bias in later trials outweigh initial bias.

notice initial bias never counterbalanced. rather, dwarfed rest of results. means bias tends zero, not guarantee bias vanishes in finite number of trials. indeed, predicts progressively smaller amounts of bias continue exist indefinitely. entirely possible algorithm never terminates, because there's tiny bit of bias still hanging around, statistically insignificant, still there.

that's bad enough, you're working floating point, has own issues; in particular, floating point arithmetic violates lots of conventional rules of math because computer keeps doing intermediate rounding ensure numbers continue fit memory, if repeating (in base 2) or irrational. fact rounding empirical percents 3 decimal places doesn't fix this, because not terminating decimals (base 10) terminating binary values (base 2), may still find mismatches between empirical , expected values. instead of doing this:

if emp_percent == expected:     break 

...you might try (in python 3.5+ only):

if all(map(math.is_close, emp_percent, expected)):     break 

this solves both problems @ once. default, math.is_close() requires values within (about) 9 decimal places of 1 another, inserts necessary give algorithm have chance of working. note require special handling comparisons involving zero, may need tweak code use case, this:

is_close = functools.partial(math.is_close, abs_tol=1e-9) if all(map(is_close, emp_percent, expected)):     break 

math.is_close() removes need round empiricals, since can approximation you:

is_close = functools.partial(math.is_close, rel_tol=1e-3, abs_tol=1e-5) if all(map(is_close, emp_percent, expected)):     break 

if don't want these approximations, have give floating point , work fractions exclusively. produce exact results when divided 1 another. however, still have problem algorithm unlikely terminate (or perhaps @ all), reasons discussed above.


Comments

Popular posts from this blog

1111. appearing after print sequence - php -

java - WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/board/] in DispatcherServlet with name 'appServlet' -

Ruby on Rails, ActiveRecord, Postgres, UTF-8 and ASCII-8BIT encodings -