对于一个大学项目,我想实现Bellard的算法,在Fortran中计算pi的第n位数。我在math.stackexchange:https://math.stackexchange.com/questions/1776840/confusion-with-bellards-algorithm-for-pi上偶然发现了这个问题
有了这个问题的答案,我成功地实现了代码,但我没有得到结果,我也不知道自己做错了什么:
PROGRAM pi
IMPLICIT NONE
INTEGER :: find_number_of_primes, number_primes, last_digit, digit, N, &
eps, i, j, multiplicity, test
REAL :: log2, base, v_max, m, s, v, b, A, pi_sum
INTEGER, ALLOCATABLE :: primes(:)
digit = 3
eps = 2
base = 10
N = INT((digit+eps)*log2(base))
pi_sum = 0
number_primes = find_number_of_primes(2*N)
ALLOCATE(primes(number_primes))
CALL get_primes(number_primes, primes)
DO i=1,SIZE(primes)
v_max = INT(log(REAL(2*N))/log(REAL(primes(i))))
m = primes(i)**v_max
s = 0
v = 0
b = 1
A = 1
DO j = 1,(N)
b = MOD((j/(primes(i)**multiplicity(digit, j)) * b), m)
A = MOD((2*j-1)/(primes(i)**multiplicity(primes(i), (2*j-1)))*A, m)
v = v - multiplicity(primes(i),j)+multiplicity(primes(i),(2*j-1))
IF (v > 0) THEN
s = MOD(s*j*b*(A**(-1))*a**(v_max-v), m)
END IF
END DO
s = MOD(s * base**(digit-1), m)
pi_sum = pi_sum + MOD((s/m), REAL(1))
END DO
PRINT*, pi_sum
END PROGRAM自定义函数find_number_of_primes、get_primes、log2和multiplicity按预期工作。首先查找给定间隔中的素数,第二个返回数组中的素数,第三个计算
log_2(x) = log(x)/log(2) 最后一个计算多重性(我猜这就是所谓的),检查第二个数被除以第一个数的频率,直到除数的其余部分不再为零。以下是源代码:
对数:
real function log2(x)
implicit none
real, intent(in) :: x
log2 = log(x) / log(2.)
end function在区间中求素数的数目:
integer function find_number_of_primes(limit) result(number_primes)
implicit none
INTEGER, INTENT(IN) :: limit
INTEGER :: i, j
LOGICAL :: is_prime
number_primes = 0
DO i = 3,(limit-1)
is_prime = .TRUE.
DO j = 2, (i-1)
IF (MODULO(i, j) == 0) THEN
is_prime = .FALSE.
EXIT
END IF
END DO
IF (is_prime .EQV. .TRUE.) THEN
number_primes = number_primes + 1
END IF
END DO
end function find_number_of_primes得到实际素数:
SUBROUTINE get_primes(number_primes, primes)
IMPLICIT NONE
INTEGER, INTENT(IN) :: number_primes
INTEGER :: i, found_primes, j
LOGICAL:: is_prime
INTEGER, INTENT(OUT) :: primes(number_primes)
i = 3
found_primes = 0
DO
is_prime = .TRUE.
DO j = 2, (i-1)
IF (MODULO(i,j) == 0) THEN
is_prime = .FALSE.
END IF
END DO
IF (is_prime .EQV. .TRUE.) THEN
found_primes = found_primes + 1
primes(found_primes) = i
IF (found_primes == number_primes) EXIT
END IF
i = i + 1
END DO
end SUBROUTINE get_primes
integer function multiplicity(a, b)
implicit none
INTEGER, INTENT(IN) :: a, b
multiplicity = 0
DO
multiplicity = multiplicity + 1
IF (MOD(b, (a**(multiplicity+1))) /= 0) THEN
EXIT
END IF
END DO
end function multiplicity整个文件的Pastebin:https://pastebin.com/0F4zQYaH
现在,在我所链接的问题中,在内环中的b的计算中,分母中有一个{v(n,k)},但是在这个问题的答案中,分母中的术语是^v(a,k)}。此外,问题中的内循环从1到N,而答案中的循环从1到2N。
最后的结果是NaN,下面是digit = 2和eps = 1的一些控制台输出:
************ i = 1 ***************************
v_max = 2.00000000
m = 9.00000000
------------- j = 1 -------------------------------
b = 0.00000000
A = 0.00000000
v = 0.00000000
------------- j = 2 -------------------------------
b = 0.00000000
A = 0.00000000
v = 0.00000000
------------- j = 3 -------------------------------
b = 0.00000000
A = 0.00000000
v = 0.00000000
------------- j = 4 -------------------------------
b = 0.00000000
A = 0.00000000
v = 0.00000000
------------- j = 5 -------------------------------
b = 0.00000000
A = 0.00000000
v = 1.00000000
v > 0 --> s = NaN
------------- j = 6 -------------------------------
b = 0.00000000
A = 0.00000000
v = 1.00000000
v > 0 --> s = NaN因此,一个完整的输出:https://pastebin.com/ucJNg6Vi
有人能帮我找出我做错了什么吗?
发布于 2018-10-16 13:37:49
您的代码中有一个bug:
v = v - multiplicity(primes(i),j)+multiplicity(primes(i),(2*j-1))应该是
v = v - multiplicity(primes(i),j)- multiplicity(primes(i),(2*j-1))另外,
s = MOD(s*j*b*(A**(-1))*a**(v_max-v), m)应该是
s = MOD(s + j*b*(A**(-1))*a**(v_max-v), m)https://stackoverflow.com/questions/52835997
复制相似问题