두 D30의 복잡한 던지기의 정확한 결과를 계산하십시오
-
08-07-2019 - |
문제
좋아, 이것은 지금 몇 년 동안 나를 괴롭혔다. 학교에서 통계와 더 높은 수학을 빨아 들으면 돌아가십시오. 지금. 너무 늦었 어.
괜찮아. 심호흡을하십시오. 규칙은 다음과 같습니다. 가져가다 둘 30 편 주사위 (예, 그들은 존재합니다)) 동시에 굴립니다.
- 두 숫자를 추가하십시오
- 두 주사위 모두 <= 5 또는> = 26을 보이면 다시 던지고 추가하다 당신이 가진 것에 대한 결과
- 하나는 <= 5이고 다른 하나는> = 26이면 다시 던지고 덜다 당신이 가진 것의 결과
- > 5와 <26이 될 때까지 반복하십시오!
코드를 작성하는 경우 (아래 참조) 주사위를 몇 백만 번 굴리면 최종 결과로 각 숫자를 얼마나 자주받는 지 계산하면 1 사이에 약 45 °, 약 45 ° °의 곡선이 1과 1의 평평한 곡선을 얻습니다. 60 이상으로 60 이상.
이제 질문 : 프로그램을 작성할 수 있습니까? 계산하다 그만큼 정확한 값 f (x), 즉 특정 값을 굴릴 확률?
배경 : 우리의 롤 플레잉 게임 "Jungle of Stars"를 위해 우리는 임의의 이벤트를 확인하는 방법을 찾았습니다. 위의 규칙은 당신이 시도한 것에 대한 훨씬 더 안정적인 결과를 보장합니다 :)
주변 괴짜의 경우 파이썬의 코드 :
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
해결책
이해하기 전에 먼저 코드를 다시 작성해야했습니다.
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
어쩌면 당신은 이것을 덜 읽기 쉽다는 것을 알 수 있습니다. 모르겠어요. (코드에서 "결과"를 사용하는 방식에 대해서도 Python의 사용 방법에 대해서도 생각하는 것과 동등한 지 확인하십시오.) DITT에스?
어쨌든, 프로그래밍 스타일의 문제는 제쳐두고 : f (x)가 CDF OW60 (1), 즉
F(x) = the probability that OW60(1) returns a value ≤ x.
마찬가지로
G(x) = the probability that OW60(-1) returns a value ≤ x.
그런 다음 첫 번째 던지기 결과의 모든 (30 × 30) 가능한 값을 합산하여 정의에서 f (x)를 계산할 수 있습니다. 예를 들어, 첫 번째 던지기가 (2,3) 인 경우 다시 굴러 가기 때문에이 용어는 (1/30) (1/30) (5+F (x-5)) F (F) 표현식에 기여합니다. 엑스). 그래서 당신은 외설적으로 긴 표현을 얻을 수 있습니다
F(x) = (1/900)(2+F(x-2) + 3+F(x-3) + ... + 59+F(x-59) + 60+F(x-60))
이는 [30] × [30]의 각 쌍 (a, b)마다 900 개 이상의 항 (A, B)입니다. ≤ 5 또는 둘 다 ≥26 인 쌍 (A, B)은 A+B+F (XAB)라는 용어를 가지며, 1 ≤5 및 1 ≥26의 쌍은 A+B+G (XAB)라는 용어를 갖고 있으며, 나머지는 다시 던지지 않기 때문에 (a+b)와 같은 용어가 있습니다.
마찬가지로 당신은 가지고 있습니다
G(x) = (1/900)(-2+F(x-2) + (-3)+F(x-3) + ... + (-59)+F(x-59) + (-60)+F(x-60))
물론 계수를 수집 할 수 있습니다. 발생하는 유일한 F 항은 F (X-60)에서 F (X-52) 및 F (X-10)에서 F (X-2)까지 (A, B≥26 또는 둘 다 5) 및 발생하는 유일한 G 항은 g (x-35)에서 G (x-27)까지 (a, b ≥26 및 다른 ≤5의 경우)이므로 30 항보다 적은 용어가 적습니다. 어쨌든 벡터 v (x)를 다음과 같이 정의합니다.
V(x) = [F(x-60) G(x-60) ... F(x-2) G(x-2) F(x-1) G(x-1) F(x) G(x)]
(예 : F 및 G에 대한 표현에서) 형식의 관계가 있습니다.
V(x) = A*V(x-1) + B
적절한 행렬 A와 적절한 벡터 B (계산할 수있는 적절한 벡터 B)의 경우 x 형식의 초기 값에서 시작하여 x의 경우 x)에서 충분히 작게 시작하면 f (x) 및 g (x)를 찾을 수 있습니다. ) 범위의 x의 경우 임의로 정밀도를 임의로 가깝게하려고합니다. (그리고 x를 던질 확률 인 f (x)는 단지 f (x) -f (x-1)이므로 나옵니다.)
더 나은 방법이있을 수 있습니다. 그래도 모든 것이 말하고 끝났습니다. 왜 이렇게하고 있습니까? 원하는 분포가 무엇이든, 적절한 매개 변수를 갖춘 멋지고 간단한 확률 분포가 있으며, 좋은 특성이 있습니다 (예 : 작은 분산, 단면 오류 등). 임의의 숫자를 생성하기 위해 자신의 임시 절차를 구성 할 이유가 없습니다.
다른 팁
나는 2 천만 던지기 샘플에 대한 몇 가지 기본 통계를 수행했습니다. 결과는 다음과 같습니다.
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)
오류는 실험적으로 결정되었다. 산술 평균과 모드는 실제로 정확하며 매개 변수를 매우 적극적으로 바꾸는 것은 그다지 영향을 미치지 않는 것 같습니다. 중앙값의 행동이 이미 설명되었다고 생각합니다.
참고 : 함수에 대한 적절한 수학적 설명을 위해이 숫자를 취하지 마십시오. 그것들을 사용하여 분포의 모습을 빠르게 얻으십시오. 다른 것에 대해, 그들은 정확하지 않더라도 충분히 정확하지 않습니다.
아마도 이것은 누군가에게 도움이 될 것입니다.
편집 2 :
991 값을 기준으로합니다. 나는 그것에 더 많은 가치를 ram 다 할 수 있었지만 결과를 왜곡했을 것입니다. 이 샘플은 상당히 일반적입니다.
편집 1 :
비교를 위해 60면 다이에 대한 위의 값은 다음과 같습니다.
Median: 30.5
Arithmetic Mean: 30.5
Standard Deviation: 7.68114574787
Root Mean Square: 35.0737318611
이 값은 실험이 아닌 계산됩니다.
화합물의 무한 확률은 ... 사소한 일입니다. 나는 James Curran과 같은 방식으로 문제를 해결하려고했지만 소스 코드에서 세 번째 롤 세트가있을 수 있음을 알았습니다. 문제는 해결할 수 있지만 대부분의 다이 롤링 시뮬레이터를 훨씬 뛰어 넘습니다.
1-60 정도의 복잡한 곡선으로 -inf에서 +inf까지 임의의 범위가 필요한 특별한 이유가 있습니까? 2D30의 벨 곡선이 허용되지 않는 이유는 무엇입니까? 요구 사항을 설명하면 누군가가 더 간단하고 경계 알고리즘을 제공 할 수 있습니다.
어디 한번 보자. 그만큼 초 던지기 (때때로 첫 번째 롤에 추가되거나 빼기)에는 31에 쉽게 예측 가능한 벨 커브가 있습니다. 물론 첫 번째 롤은 문제입니다.
첫 번째 롤의 경우 900 개의 가능한 조합이 있습니다.
- 50 조합으로 인해 두 번째 롤이 추가됩니다.
- 25 조합으로 인해 두 번째 롤을 빼냅니다.
- 두 번째 롤의 벨 곡선과 일치하는 825 조합을 남겨 둡니다.
빼기 세트 (사전 세포화)는 범위 (27..35)에서 벨 곡선을 형성합니다. 추가 세트의 하단 절반은 범위 (2..10)에서 벨 곡선을 형성하는 반면 상단 절반은 범위 (52 ... 60)의 벨 곡선을 형성합니다.
내 프로블은 약간 녹슬으므로 정확한 값을 알 수는 없지만 이로 인해 예측 가능한 값이 이루어지는 것이 분명해야합니다.