확률 계산하는 알고리즘 자바 코드 좀 짜주세요... (아니면 계산식이라도)

확률 계산하는 알고리즘 자바 코드 좀 짜주세요... (아니면 계산식이라도)

작성일 2023.10.15댓글 1건
    게시물 수정 , 삭제는 로그인 필요

나오는 물품의 갯수 (총합: 100%)
1: 25%
2: 55%
3: 15%
4: 5%

나오는 물품 (추첨 순서, 기본 확률)
A: 1, 20%
B: 2, 30%
C: 3, 25%
D: 4, 50%

이런 뽑기 표가 있습니다.
뽑기가 시작되면 먼저 나올 물품의 총 갯수가 정해집니다. 확률은 위 표의 확률을 따르고요.
정해진 물품의 갯수를 n개라고 해볼게요.
이후 추첨 순서가 높은 물품부터 추첨을 시작합니다. 저 위에선 A가 첫번째이니, A부터 시작하겠죠. 물품의 기본 확률이 이루어졌다면 나올 물품 목록에 해당 물품이 추가됩니다.
이런 식으로 해서 나올 물품 목록의 물품 갯수가 n개가 될 때까지 전체 나오는 물품을 추첨 순서대로 추첨합니다. 만약 추첨 순서 끝까지 갔다면 처음부터 다시 추첨합니다.

이런 알고리즘인데, 추첨하는 코드는 저도 쉽게 짤 수 있습니다. 근데 문제는, 이런 환경에서 나오는 물품 하나의 나올 확률이 있을텐데, 그 확률을 구하는 코드가 쉽지 않다는 것입니다. 즉, A의 나올 확률은 그냥 아무 조건 없이 뽑기를 딱 눌렀을 때 나온 물품들 중에서 A가 있을 확률을 말하는 겁니다. 예시를 들어봅시다.

A: 나올 확률 = A가 뽑힐 확률 = 20% (A는 추첨 순위가 제일 첫번째이므로 나오는 물품의 갯수나 다른 물품의 확률에 영향을 받지 않음)

B: 나올 확률 =
  나오는 물품의 갯수가 2개 이상이면서 B가 뽑힐 확률
+ 나오는 물품의 갯수가 2개 미만이면서 A가 뽑히지 않은 채로 B가 뽑힐 확률

= (나오는 물품의 갯수가 2개 이상일 확률) * (B가 뽑힐 확률)
+ (나오는 물품의 갯수가 2개 미만일 확률) * (A가 뽑히지 않을 확률) * (B가 뽑힐 확률)

= (5% + 55% + 15%) * 30%
 + 25% * 80% * 30%
= 22.5% + 6%
= 28.5%

제가 확률에 좀 약해서 이렇게 계산하는게 맞나 싶긴 한데, 이런 식으로 "기본 확률"과 "나올 확률"은 다를 수 있다는 것입니다. 또한 C 계산 부터는 훨씬 더 복잡해집니다.
그리고 저는 나오는 물품의 갯수와 나오는 물품이 앞서 제시한 예제보다 훠얼씬 많은 데이터를 가지고 있고, 이를 자바 코드를 사용해 계산하려 합니다. 앞서 말했듯이 확률에 약해서 어떻게 짤지 도무지 모르겠습니다. ㅜㅜ
getAmountChance(int)로 나오는 물품의 갯수가 int개일 확률을 구하고 (0~100 사이의 double 형),
물품은 대충 item이라 치고 item.getChance()로 0~100 사이의 double형 기본 확률을, item.getWeight()로 int형 우선순위를 구할 수 있는 구조입니다. getFromWeight(int)로 우선순위가 int인 item도 얻을 수 있습니다.

이런 구조를 통해 계산된 "나올 확률"을 반환하는 메소드 코드를 짜주세요. 오늘 하루종일 이거만 고민하다 결국 포기하고 여기에 질문해보네요ㅜ ChatGPT한테도 여러번 질문했는데 위에 같은 조건에서 B 확률 구하라 했더니 40.5%라고 해서 그냥 때려쳤습니다... 계산도 제대로 못합니다.

코드 실행해보고 제대로 작동하면 채택 드리겠습니다.
아니면 확률 계산만 잘하시는 분은 계산하는 식이라도 써주시면 직접 자바로 구현해보겠습니다... 부탁드립니다.




#확률 계산하는 법

profile_image 익명 작성일 -

N = 1일 때 A가 나올 확률은 20%가 아닙니다.

첫번째 시도에 A, B, C, D 모두 나오지 않을 수 있죠.

그러면 A가 다시 뽑힐 수 있는 기회가 옵니다.

그렇기 때문에 A가 나올 확률은 20%보다 높습니다.

이런 문제는 공식으로는 계산할 수 없는 문제입니다.

이런 류의 문제는 통계적 확률로 해결합니다.

별거 없습니다.

X번 돌려서 나온 확률을 그냥 답으로 제시하면 됩니다.

A : 37.0067% B : 48.97% C : 36.1273% D : 56.6749%

코드는 JAVA가 좀 서툴러서 C++로 올립니다.

#include <iostream> using namespace std; #include <ctime> #include <cstdlib> size_t A[4] = { 0, 0, 0, 0 }; const size_t CNT = 100000000; const double R[4] = { 2.0, 3.0, 2.5, 5.0 }; int main() { srand((unsigned)time(0)); for (size_t i = 0; i < CNT; i++) { double rnd = (rand() % 32768) / 3276.8; // 0 ~ 9.999999 size_t N = (rnd < 2.5 ? 1 : (rnd < 8. ? 2 : (rnd < 9.5 ? 3 : 4))); size_t C = 0, X[4] = { 0, }; while (N > 0) { rnd = (rand() % 32768) / 3276.8; if (rnd < R[C]) --N, X[C] = 1; C = (C + 1) % 4; } for (C = 0; C < 4; C++) A[C] += X[C]; } for (size_t i = 0; i < 4; i++) { cout << (char)('A' + i) << " : "; cout << (A[i] / (double)CNT) * 100 << "%" << endl; } return 0; }
A : 37.004% B : 48.9715% C : 36.1254% D : 56.6769%
A : 36.9993% B : 48.968% C : 36.1288% D : 56.6834%

A : 37.00%

B : 48.97%

C : 36.13%

D : 56.68%

아래는 N별 확률

#include <iostream> using namespace std; #include <ctime> #include <cstdlib> const size_t CNT = 100000000; size_t A[5][4] = { 0, }, TN[5] = { 0, }; const double R[4] = { 2.0, 3.0, 2.5, 5.0 }; int main() { srand((unsigned)time(0)); for (size_t i = 0; i < CNT; i++) { double rnd = (rand() % 32768) / 3276.8; // 0 ~ 9.999999 size_t N = (rnd < 2.5 ? 1 : (rnd < 8. ? 2 : (rnd < 9.5 ? 3 : 4))); TN[N]++; size_t C = 0, T = N, X[4] = { 0, }; while (N > 0) { rnd = (rand() % 32768) / 3276.8; if (rnd < R[C]) --N, X[C] = 1; C = (C + 1) % 4; } for (C = 0; C < 4; C++) A[T][C] += X[C]; } for (size_t N = 1; N <= 4; N++) { cout << "[ N : " << N << " ]" << endl; for (size_t i = 0; i < 4; i++) { cout << (char)('A' + i) << " : "; cout << (A[N][i] / (double)TN[N]) * 100 << "%" << endl; } } return 0; }
[ N : 1 ] A : 25.3232% B : 30.3908% C : 17.7082% D : 26.5778% [ N : 2 ] A : 37.1781% B : 50.7589% C : 37.6522% D : 60.6318% [ N : 3 ] A : 48.8282% B : 64.7086% C : 52.1562% D : 81.0004% [ N : 4 ] A : 58.0589% B : 74.8901% C : 63.3285% D : 90.6918%