resultado exato Calcular de lance complexo de dois D30
-
08-07-2019 - |
Pergunta
Ok, isso me incomodava há vários anos, agora. Se você sugado em estatística e matemática avançada na escola, afastam-se, agora . Muito tarde.
Ok. Respire fundo. Aqui estão as regras. Tome dois trinta lados dados (sim, eles existem ) and roll-los simultaneamente.
- Adicione os dois números
- Se ambos os dados mostram <= 5 ou> = 26, joga novamente e Adicionar o resultado para o que você tem
- Se um é <= 5 e outro> = 26, joga novamente e subtrair o resultado do que você tem
- Repita até que é> 5 e <26! ??
Se você escrever algum código (ver abaixo), jogar esses dados alguns milhões de vezes e você contar quantas vezes você receber cada número como o resultado final, você tem uma curva que é bastante plana deixou de 1, cerca de 45 ° graus entre 1 e 60 e acima plana 60. a possibilidade de rolo de 30,5 ou superior é maior do que 50%, ao rolo melhor do que 18% e é de 80 a rolo melhor do que 0 é de 97%.
Agora, a pergunta:? É possível escrever um programa para calcular exata ??em> valor f (x), ou seja, a probabilidade de rolar um certo valor
Antecedentes: Para o nosso Role Playing Game "Jungle of Stars" buscamos uma maneira de manter eventos aleatórios em cheque. As regras acima garantir um resultado muito mais estável para algo que você tente:)
Para os geeks ao redor, o código em Python:
import random
import sys
def OW60 ():
"""Do an open throw with a "60" sided dice"""
val = 0
sign = 1
while 1:
r1 = random.randint (1, 30)
r2 = random.randint (1, 30)
#print r1,r2
val = val + sign * (r1 + r2)
islow = 0
ishigh = 0
if r1 <= 5:
islow += 1
elif r1 >= 26:
ishigh += 1
if r2 <= 5:
islow += 1
elif r2 >= 26:
ishigh += 1
if islow == 2 or ishigh == 2:
sign = 1
elif islow == 1 and ishigh == 1:
sign = -1
else:
break
#print sign
#print val
return val
result = [0] * 2000
N = 100000
for i in range(N):
r = OW60()
x = r+1000
if x < 0:
print "Too low:",r
if i % 1000 == 0:
sys.stderr.write('%d\n' % i)
result[x] += 1
i = 0
while result[i] == 0:
i += 1
j = len(result) - 1
while result[j] == 0:
j -= 1
pSum = 0
# Lower Probability: The probability to throw this or less
# Higher Probability: The probability to throw this or higher
print "Result;Absolut Count;Probability;Lower Probability;Rel. Lower Probability;Higher Probability;Rel. Higher Probability;"
while i <= j:
pSum += result[i]
print '%d;%d;%.10f;%d;%.10f;%d;%.10f' % (i-1000, result[i], (float(result[i])/N), pSum, (float(pSum)/N), N-pSum, (float(N-pSum)/N))
i += 1
Solução
Eu tive que primeiro reescrever seu código antes que eu pudesse entendê-lo:
def OW60(sign=1):
r1 = random.randint (1, 30)
r2 = random.randint (1, 30)
val = sign * (r1 + r2)
islow = (r1<=5) + (r2<=5)
ishigh = (r1>=26) + (r2>=26)
if islow == 2 or ishigh == 2:
return val + OW60(1)
elif islow == 1 and ishigh == 1:
return val + OW60(-1)
else:
return val
Talvez você pode encontrar este menos legível; Eu não sei. (Verificação de fazer se ele é equivalente ao que você tinha em mente.) Além disso, em relação à maneira como você usa "resultado" em seu código - você sabe de Python dict s?
De qualquer forma, questões de estilo de programação de lado: Suponha que F (x) é a CDF de OW60 (1), isto é,
F(x) = the probability that OW60(1) returns a value ≤ x.
Da mesma forma vamos
G(x) = the probability that OW60(-1) returns a value ≤ x.
Em seguida, você pode calcular F (x) a partir da definição, pela soma sobre todos (30 × 30) possíveis valores do resultado do primeiro lance. Por exemplo, se o primeiro lance é (2,3), então você vai rolar de novo, então este prazo contribui (1/30) (1/30) (5 + F (x-5)) para a expressão para F ( x). Então você vai ter alguns obscenamente longa expressão como
F(x) = (1/900)(2+F(x-2) + 3+F(x-3) + ... + 59+F(x-59) + 60+F(x-60))
que é uma soma sobre 900 termos, um para cada par (a, b) em [30] × [30]. Os pares (a, b), com ambos = 5 ou ambos =26 têm um prazo a + b + F (xab), os pares com um =5 e um =26 têm um prazo a + b + G (xab), e o resto tem um termo como (a + b), porque você não jogue novamente.
Da mesma forma que você tem
G(x) = (1/900)(-2+F(x-2) + (-3)+F(x-3) + ... + (-59)+F(x-59) + (-60)+F(x-60))
Claro, você pode coletar coeficientes; as únicas condições F que ocorrem são a partir de F (x-60) a F (x-52) e de F (x-10) a F (x-2) (para uma, ou b=26 both=5), e as únicas condições G que ocorrem são de G (x-35) a G (x-27) (para uma de, uma b=26 e o ??outro =5), de modo que há menos do que 30 termos termos. Em qualquer caso, definindo o vector V (x) como o
V(x) = [F(x-60) G(x-60) ... F(x-2) G(x-2) F(x-1) G(x-1) F(x) G(x)]
(digamos), você tem (a partir dessas expressões para F e G) uma relação de forma
V(x) = A*V(x-1) + B
para uma matriz apropriada A e uma apropriada vector B (que pode calcular), de modo a começar a partir dos valores iniciais de forma V (x) = [0 0] para x suficientemente pequeno, pode encontrar F (x) e G (x) para x no intervalo que deseja arbitrariamente próximo precisão. (E o seu f (x), a probabilidade de jogar x, é apenas F (x) -F (x-1), de modo que sai bem.)
Pode haver uma maneira melhor. Tudo dito e feito, porém, por que você está fazendo isso? Qualquer tipo de distribuição que você quer, existem distribuições de probabilidade agradável e simples, com os parâmetros apropriados, que têm boas propriedades (por exemplo variação pequena, os erros de um lado, qualquer que seja). Não há nenhuma razão para fazer o seu próprio procedimento ad-hoc para gerar números aleatórios.
Outras dicas
Eu fiz algumas estatísticas básicas sobre uma amostra de 20 milhões de lança. Aqui estão os resultados:
Median: 17 (+18, -?) # This result is meaningless
Arithmetic Mean: 31.0 (±0.1)
Standard Deviation: 21 (+1, -2)
Root Mean Square: 35.4 (±0.7)
Mode: 36 (seemingly accurate)
Os erros foram determinadas experimentalmente. A média aritmética eo modo são realmente precisa, e alterando os parâmetros ainda bastante agressiva parece não influenciá-los muito. Suponho que o comportamento da mediana já foi explicado.
Nota: não tome esses números para uma descrição matemática adequada da função. Usá-los para obter rapidamente uma imagem do que os olhares de distribuição gosta. Para qualquer outra coisa, eles são o suficiente para não preciso (embora possam ser mais preciso.
Talvez este seja útil para alguém.
Edit 2:
Com base em apenas 991 valores. Eu poderia ter amontoados mais valores para ele, mas eles teriam distorcido o resultado. Esta amostra passa a ser bastante típico.
Editar 1:
aqui estão acima valores para apenas um dado sessenta e face, para comparação:
Median: 30.5
Arithmetic Mean: 30.5
Standard Deviation: 7.68114574787
Root Mean Square: 35.0737318611
Note-se que estes valores são calculados, não experimental.
probabilidade ilimitada Composto é ... não-trivial. Eu estava indo para enfrentar o problema da mesma forma que James Curran, mas então eu vi do seu código fonte que poderia haver um terceiro conjunto de rolos, e uma quarta, e assim por diante. O problema pode ser resolvido, mas muito além maioria dos simuladores rolando die.
Há alguma razão especial que você precisa de um intervalo aleatório de -Inf para + Inf com uma curva tão complexo em torno de 1-60? Porque é que a curva do sino de 2D30 não é aceitável? Se você explicar suas necessidades, é provável que alguém poderia fornecer um algoritmo mais simples e mais limitada.
Bem, vamos ver. O segunda throw (que, por vezes, ser adicionado ou subtraído para o primeiro rolo) tem um bom facilmente curva de sino previsível em torno de 31. O primeiro rolo, é claro, é o problema.
Para o primeiro rolo, temos 900 combinações possíveis.
- 50 combinações resultam em adicionar o segundo rolo.
- 25 combinações resultam em subtrair o segundo rolo.
- Deixando 825 combinações que correspondem a curva do sino do segundo rolo.
O conjunto de subtracção (pré-subtração) irá formar uma curva de sino na gama (27..35). A metade inferior do conjunto adicionando vai formar uma curva de sino na gama (2..10), enquanto a metade superior irá formar uma curva de sino no intervalo (52 ... 60)
Meu probablity é um pouco enferrujado, então eu não consigo descobrir os valores exatos para você, mas deve ficar claro que estas levam a valores previsíveis.