简体   繁体   中英

Is randint function in Python different from % trick?

I appreciate your help in advance.

I wrote a probability calculator with python. Prob I want to calculate is this: What's the prob of winning when you try 6 times of game that has winning chance of 1%. So this following code is what I wrote.

import random as rand

total = 0
count = 0

p = pSum = 0

k = 6
n = 10000
m = 100

def pick(attemptPerIteration):
    global total, count
    for _ in range(attemptPerIteration):
        temp = rand.randint(1, 100)
        if (temp == 1):
            count += 1
            total += 1
            return 0
    return 1

for t in range(m):
    for u in range(n):
        total += pick(k)
    p = count / total
    print(str(t + 1) + ": " + str(p * 100))
    pSum += p
    p = 0
print(pSum / m * 100)

In this code, I used randint function to simulate one in 100 chance. The prob I expected is about 5.8% but this program outputs about 6.3%. But if I use randint(1, 1000) % 6 + 1 insted of just randint(1, 6), program tell the prob is 5.8, which I expected.

What's going on in this randint function exactly? Why the old % trick works but randint doesn't?

Mathematical formula to this problem is this:在此处输入图像描述

Looks like you made mistakes with incrementing count and total . I changed your code to compute correct result:

Try it online!

import random as rand

total = 0
count = 0

p = pSum = 0

k = 6
n = 10000
m = 100

def pick(attemptPerIteration):
    for _ in range(attemptPerIteration):
        temp = rand.randint(1, 100)
        if (temp == 1):
            return 1
    return 0

for t in range(m):
    for u in range(n):
        count += pick(k)
        total += 1
    p = count / total
    print(str(t + 1) + ": " + str(p * 100))
    pSum += p
    p = 0
print(pSum / m * 100)

Output:

.......
90: 5.822555555555556
91: 5.8221978021978025
92: 5.822608695652174
93: 5.824193548387097
94: 5.822446808510638
95: 5.822631578947368
96: 5.824166666666667
97: 5.825670103092784
98: 5.8254081632653065
99: 5.826969696969697
100: 5.8306
5.825542887205491

It looks like m = 100 and n = 10000 are too little for things to converge.

import random

def did_win(attempts):
    return any(random.random() < .01 for attempt in range(attempts))

tries = [did_win(6) for x in range(1_000_000)]
print(tries.count(True) / len(tries))

prints out about 0.058039 which seems close enough.

If you want to watch the solution converge in more real time,

import random
import itertools


def did_win(attempts):
    return any(random.random() < 0.01 for attempt in range(attempts))


wins = 0
for x in itertools.count(0):
    if did_win(6):
        wins += 1
    if x and x % 10_000 == 0:
        print(x, wins / x)

(hit ctrl-c to interrupt it – it'll otherwise happily run forever).

The formula is much simpler, actually. The probability of not winning is (99 / 100) ** 6 , that is approximately 0.941 . Its complement is the probability of winning 1 - 0.941... = 0.058... .

Because you are increasing global counts in a weird way, it's very likely that you have off-by-one errors in more than one place. For instance

total += pick(k)

where pick also modifies total ...

You should just return 0 or 1 and then count from outside.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM