Я изучаю курс численных методов, и меня попросили реализовать знаменитый алгоритм Монте-Карло, чтобы найти число пи, которое вы можете найти здесь.
У меня не возникло затруднений с написанием кода с произвольным количеством попыток:
REAL(8) FUNCTION distance(xvalue, yvalue) RESULT(dist)
IMPLICIT NONE
REAL(8), INTENT(in) :: xvalue, yvalue
dist = SQRT(xvalue**2 + yvalue**2)
END FUNCTION distance
PROGRAM ass2
IMPLICIT NONE
INTEGER, DIMENSION(1) :: SEED
REAL(8) :: p, x, y
REAL(8), EXTERNAL :: distance
REAL(8) :: pi_last, pi
INTEGER :: npc, npt, i
npc = 0
npt = 0
pi = 1.0
SEED(1) = 12345
CALL RANDOM_SEED
DO i=1, 1000000000
CALL RANDOM_NUMBER(p)
x = p
CALL RANDOM_NUMBER(p)
y = p
npt = npt + 1
IF (distance(x, y) < 1.0) THEN
npc = npc + 1
END IF
pi_last = pi
pi = 4.0*(npc*1.0)/(npt*1.0)
END DO
PRINT*, 'Pi:', pi
END PROGRAM ass2
Я заметил, что он сходится примерно как sqrt (N шагов). Теперь мне нужно остановить алгоритм с определенной точностью, поэтому я создал бесконечный цикл DO с EXIT внутри оператора IF:
REAL(8) FUNCTION distance(xvalue, yvalue) RESULT(dist)
IMPLICIT NONE
REAL(8), INTENT(in) :: xvalue, yvalue
dist = SQRT(xvalue**2 + yvalue**2)
END FUNCTION distance
PROGRAM ass2
IMPLICIT NONE
INTEGER, DIMENSION(1) :: SEED
REAL(8) :: p, x, y
REAL(8), EXTERNAL :: distance
REAL(8) :: pi_last, pi
INTEGER :: npc, npt, i
npc = 0
npt = 0
pi = 1.0
SEED(1) = 12345
CALL RANDOM_SEED
DO
CALL RANDOM_NUMBER(p)
x = p
CALL RANDOM_NUMBER(p)
y = p
npt = npt + 1
IF (distance(x, y) < 1.0) THEN
npc = npc + 1
END IF
pi_last = pi
pi = 4.0*(npc*1.0)/(npt*1.0)
IF ( ABS(pi - pi_last) < 0.000001 .AND. pi - pi_last /= 0) THEN
EXIT
END IF
END DO
PRINT*, 'Pi:', pi
END PROGRAM ass2
Проблема в том, что это возвращает значение пи, которое не имеет той точности, о которой я просил. Я понимаю логику этого: если я получаю два последовательных значения, далеко от пи, но близко друг к другу, условие будет выполнено, и программа выйдет из оператора DO. Проблема в том, что я не знаю, как изменить его, чтобы добиться определенной мной точности. Итак, вопрос:
Как мне реализовать этот алгоритм таким образом, чтобы я мог определять точность вывода числа Пи?
РЕДАКТИРОВАТЬ: Хорошо, я реализовал оба ваших решения, и они работают, но только для 10 ^ (- 1), 10 ^ (- 3) и 10 ^ (- 5). Я думаю, что это проблема псевдослучайной последовательности, если для 10 ^ (- 2) и 10 ^ (- 4) она возвращает неправильное значение числа пи.
real(8)
, бог убивает котенка http://stackoverflow.com/questions/838310/fortran-90-kind-parameter - person Vladimir F   schedule 12.10.2015Pi
? Если вы не знали результата, вам потребовались бы более сложные критерии, например отслеживание нескольких последних сотен результатов. - person agentp   schedule 13.10.2015