Binomial random variable. Gives the number of successes for *n* independent trials with the probability of success in each trial being *p*: sum(random() < p for i in range(n)) Returns an integer in the range: 0 <= X <= n The integer is cho
(self, n=1, p=0.5)
| 787 | ## -------------------- discrete distributions --------------------- |
| 788 | |
| 789 | def binomialvariate(self, n=1, p=0.5): |
| 790 | """Binomial random variable. |
| 791 | |
| 792 | Gives the number of successes for *n* independent trials |
| 793 | with the probability of success in each trial being *p*: |
| 794 | |
| 795 | sum(random() < p for i in range(n)) |
| 796 | |
| 797 | Returns an integer in the range: |
| 798 | |
| 799 | 0 <= X <= n |
| 800 | |
| 801 | The integer is chosen with the probability: |
| 802 | |
| 803 | P(X == k) = math.comb(n, k) * p ** k * (1 - p) ** (n - k) |
| 804 | |
| 805 | The mean (expected value) and variance of the random variable are: |
| 806 | |
| 807 | E[X] = n * p |
| 808 | Var[X] = n * p * (1 - p) |
| 809 | |
| 810 | """ |
| 811 | # Error check inputs and handle edge cases |
| 812 | if n < 0: |
| 813 | raise ValueError("n must be non-negative") |
| 814 | if p <= 0.0 or p >= 1.0: |
| 815 | if p == 0.0: |
| 816 | return 0 |
| 817 | if p == 1.0: |
| 818 | return n |
| 819 | raise ValueError("p must be in the range 0.0 <= p <= 1.0") |
| 820 | |
| 821 | random = self.random |
| 822 | |
| 823 | # Fast path for a common case |
| 824 | if n == 1: |
| 825 | return _index(random() < p) |
| 826 | |
| 827 | # Exploit symmetry to establish: p <= 0.5 |
| 828 | if p > 0.5: |
| 829 | return n - self.binomialvariate(n, 1.0 - p) |
| 830 | |
| 831 | if n * p < 10.0: |
| 832 | # BG: Geometric method by Devroye with running time of O(np). |
| 833 | # https://dl.acm.org/doi/pdf/10.1145/42372.42381 |
| 834 | x = y = 0 |
| 835 | c = _log2(1.0 - p) |
| 836 | if not c: |
| 837 | return x |
| 838 | while True: |
| 839 | y += _floor(_log2(random()) / c) + 1 |
| 840 | if y > n: |
| 841 | return x |
| 842 | x += 1 |
| 843 | |
| 844 | # BTRS: Transformed rejection with squeeze method by Wolfgang Hörmann |
| 845 | # https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.47.8407&rep=rep1&type=pdf |
| 846 | assert n*p >= 10.0 and p <= 0.5 |