트랙
/
Julia
Julia
/
연습 문제
/
문제투성이 확률
문제투성이 확률

문제투성이 확률

학습 연습 문제

소개

Rational numbers는 정수 분자를 정수 분모로 나눈 분수예요.

예를 들어 2//3을 근삿값인 Float64 값 0.6666... 대신 정확한 분수로 저장할 수 있어요.

장점은 (integer overflow라는 극단적인 경우만 빼면) 유리수가 정확한 값을 그대로 유지해서, 부동소수점 수에서 흔히 피할 수 없는 반올림 오류를 피할 수 있다는 점이에요.

유리수는 아주 단순한 숫자 타입이고, 기대하는 대로 동작하도록 만들어졌어요. 초기 버전부터 Julia의 표준 타입이었기 때문에, 대부분의 함수가 정수나 실수에서처럼 유리수도 입력으로 받아요.

유리수 만들기

만드는 방법은 간단해요. 두 정수 사이에 //를 쓰면 돼요.

julia> 3//4
3//4

julia> a = 3; b = 4;

julia> a//b
3//4

공통 인수는 자동으로 제거되어 분수가 "가장 간단한 형태"로 바뀌어요. 즉, 그 분수를 정확히 나타내는 가장 작은 정수들이 되고, 분모는 음수가 아니에요.

julia> 5//15
1//3

julia> 5//-15
-1//3

유리수의 계산

일반적인 arithmetic operators인 + - * / ^ %는 유리수에서도 다른 숫자 타입과 거의 똑같이 동작해요.

정수와 다른 Rational들을 함께 써도 결과는 Rational이에요. 식에 float을 포함하면 결과도 float이 되고, 그에 따라 정밀도가 (어쩌면) 떨어질 수 있어요.

float이 필요하면 그냥 float() 함수로 유리수를 변환하면 돼요. 긴 계산 동안 정밀도를 유지하려고 유리수를 쓰고, 마지막에 실수로 변환하는 건 아주 흔한 일이에요.

julia> 3//4 + 1//3  # addition
13//12

julia> 3//4 * 1//3  # multiplication
1//4

julia> 3//4 / 1//3  # division
9//4

julia> 3//4 ^ 2  # exponentiation
3//16

julia> 3//4 + 5  # rational and int => rational
23//4

julia> 3//4 + 5.3  # rational and float => float
6.05

julia> float(3//4)  # casting
0.75

그 밖의 연산

Julia에서 유리수는 그냥 숫자예요. 컴파일러가 보통 필요에 따라 타입을 변환해 줘요.

다만 비교는 유한 소수로 나타낼 수 있는 분수에서만 기대한 대로 동작하니 주의해요.

julia> 3//4 == 0.75
true

julia> 3//4 < 0.74
false

그 밖의 경우에는 비교하려면 Rational을 Float로 변환해야 해요.

julia> 1//3 == 1/3
false

julia> float(1//3) == 1/3
true

수학 함수는 유리수를 입력으로 받지만, 부동소수점 결과를 내놓을 수도 있어요.

julia> sqrt(9//16)
0.75

지침

어느 연구 기관은 신입 연구원 일부가 분석에서 최선이 아닌 방법을 사용해 왔다는 것을 알아챘어요. 그중 하나는 추가 계산을 하기 전에 이산 확률을 실수(즉, 부동소수점 수)로 곧바로 변환하는 방법이에요.

선임 연구원들은 더 높은 정밀도를 얻을 수 있는 유리수를 계산에 사용하는 쪽을 선호하고, 신입 연구원들의 좋지 않은 관행이 연구 결과에 영향을 주었는지 알고 싶어 해요.

수행된 연구에는 두 가지 유형이 있었어요.

  • 많은 시험을 실행해 각 시험에서 성공에 대한 이산 확률을 얻은 다음, 이 확률들의 평균을 계산했어요.
  • 많은 독립 사건을 시험하고, 모든 사건이 일어날 전체 확률을 각 확률을 곱해서 계산했어요.

선임 연구원들은 실수를 사용한 분석에 반올림 오류가 있는지 판단하는 데 도움이 될 함수를 작성해 달라고 요청해요. 그리고 오류가 있다면 결과에 대한 정확한 유리수를 제공해 달라고도 해요.

1. 성공 횟수와 시행 횟수의 비율 구하기

rationalize(successes, trials) 함수는 successes와 trials 두 배열을 받아요. 인덱스 i에 대해, successes[i]는 trials[i]번의 시행에서 일어난 성공 횟수에 해당해요. 이 함수는 입력 배열과 같은 순서로, 시행 횟수에 대한 성공 횟수의 유리수 배열을 반환해요.

julia> rationalize([1, 2, 3], [4, 5, 6])
3-element Vector{Rational{Int64}}:
 1//4
 2//5
 1//2

2. 성공 횟수와 시행 횟수에 대응하는 실수 확률 구하기

마찬가지로, probabilities(successes, trials) 함수는 successes와 trials 두 배열을 받아요. 입력 배열과 같은 순서로, 시행 횟수에 대한 성공 횟수의 실수 배열을 반환해요.

julia> probabilities([1, 2, 3], [4, 5, 6])
3-element Vector{Float64}:
 0.25
 0.4
 0.5

3. 확률의 평균 확인하기

checkmean(successes, trials)는 successes와 trials 두 배열을 받아요. 실수 확률의 평균과 유리수 확률의 평균을 비교해요.

  • 두 확률이 같으면, checkmean은 true를 반환해요.
  • 두 확률이 다르면, checkmean은 유리수 확률을 반환해요.
julia> successes, trials = [9, 4, 7, 8, 6], [22, 22, 11, 17, 12];
julia> checkmean(successes, trials)
true

julia> successes, trials = [6, 5, 9, 8, 9], [21, 19, 13, 25, 22];
julia> checkmean(successes, trials)
1873629//4754750

4. 독립 확률 확인하기

checkprob(successes, trials)는 successes와 trials 두 배열을 받아요. 실수 확률의 전체 확률과 유리수 확률의 전체 확률을 비교해요.

  • 두 확률이 같으면, checkprob은 true를 반환해요.
  • 두 확률이 다르면, checkprob은 유리수 확률을 반환해요.
julia> successes, trials = [2, 9, 4, 4, 5], [15, 11, 17, 19, 15];
julia> checkprob(successes, trials)
true

julia> successes, trials = [9, 8, 5, 4, 3], [22, 14, 19, 25, 18];
julia> checkprob(sucesses, trials)
12//7315
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Julia Exercism

문제투성이 확률 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Julia 트랙을 개념 35개연습 문제 128개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.