조삿갓 VBA 코드 짜고 있는데 코알라님께서 함수로 답을 주셨네요?
문제는 a=b+c+d+e+f+g+h라는데
각각 요소의 최솟값끼리 더한 결과는 490이고
최댓값끼리 더한 결과는 630이라는 게 문제네요.
따라서 단순히 난수 7개를 각 범위별로 발생시키면
a값이 범위 밖의 값이 나올 수 있다는 것이지요.
결국 VBA가 더 편한 해결 방법이네요. 09-15 (21:17) ⓧ 삭제 ■신고
조삿갓 Function RndNumber(ByRef RndElement() As Double) As Double
Const most = 530
Const least = 500
Dim i As Integer
Dim a As Double
Dim r As Integer
Dim rBase As Variant
Randomize Timer
rBase = Array(20, 30, 120, 140, 110, 50, 20)
Do
a = 0
For i = 0 To 6
r = Int(Rnd() * 200)
RndElement(i) = r / 10 + rBase(i)
a = a + RndElement(i)
Next i
Loop Until a >= least And a <= most
RndNumber = a
End Function 09-15 (21:49) ⓧ 삭제 ■신고
조삿갓 위와 같이 하면 되겠습니다.
함수로 작성했으니 필요한 곳에서 이 함수를 호출하면 됩니다.
a의 값은 함수 결과 값으로
그리고 각 요소인 b~h는 배열로 반환합니다.
(이런 성격의 프로그램은 배열을 사용하는 게 효율적이니까요)
예를 들면 다음과 같이 사용하시면 됩니다
Sub test()
Dim a As Double
Dim i As Integer
Dim e(6) As Double
a = RndNumber(e)
Debug.Print "a="; a
For i = 0 To 6
Debug.Print "e(";i;")="; e(i)
Next i
End Sub 09-15 (21:49) ⓧ 삭제 ■신고
조삿갓 참고로
r = Int(Rnd() * 200)
RndElement(i) = r / 10 + rBase(i)
두 줄을
RndElement(i) = Int(Rnd() * 200) / 10 + rBase(i)
이렇게 해도 될 것 같은데
실제로는 이진수 변환 오차 때문에
소수 첫째 자리로 떨어지지 않고 무한소수가 나옵니다.
09-15 (21:57) ⓧ 삭제 ■신고
코알라 RndElement(i) = CInt(Rnd() * 200) / 10 + rBase(i) 09-15 (22:59) ⓧ 삭제 ■신고
조삿갓 아하, 형변환 함수에서는 무한소수 오차가 발생하지 않네요.
그런데, Int(3.5) = 3 인데 Int(3.5) = 4 로 반올림한다는 차이가 또 신경이 쓰입니다만, 실험 결과로는 오히려 이게 질문자의 의도와 맞는 프로그램이 될 것 같네요.
수학적으로 Rnd 함수는 0 이상 1 미만의 난수를 발생하므로
원래의 코드대로 하면 b 값은 20.0~39.9까지만 나오지요. 그런데 반올림해 버리니까 가끔씩 40이 나옵니다. 물론 확률이 공평하지 않지만, 또 a의 범위 제한 때문에 최솟값이나 최댓값이 배제되고 다시 루프를 도는 현상이 발생하니까 대충 실용상 지장은 없을 것 같습니다.
코알라님 감사합니다. 항상 많이 배우네요. 09-16 (00:37) ⓧ 삭제 ■신고
조삿갓 공평한 확률 만들기
20.0 ~ 39.9
RndElement(i) = CInt(Rnd() * 200 - 0.5) / 10 + rBase(i)
20.0 ~ 40.0
RndElement(i) = CInt(Rnd() * 201 - 0.5) / 10 + rBase(i) 09-16 (00:42) ⓧ 삭제 ■신고