como - parameter fortran
Por qué definir PI=4*ATAN(1.d0) (6)
Creo que es porque esta es la serie más corta en pi. Eso también significa que es el MÁS EXACTO.
La serie Gregory-Leibniz (4/1 - 4/3 + 4/5 - 4/7 ...) es igual a pi.
atan (x) = x ^ 1/1 - x ^ 3/3 + x ^ 5/5 - x ^ 7/7 ...
Entonces, atan (1) = 1/1 - 1/3 + 1/5 - 1/7 + 1/9 ... 4 * atan (1) = 4/1 - 4/3 + 4/5 - 4 / 7 + 4/9 ...
Eso equivale a la serie Gregory-Leibniz, y por lo tanto es igual a pi, aproximadamente 3.1415926535 8979323846 2643383279 5028841971 69399373510.
Otra forma de usar atan y encontrar pi es:
pi = 16 * atan (1/5) - 4 * atan (1/239), pero creo que eso es más complicado.
¡Espero que esto ayude!
(Para ser honesto, creo que la serie de Gregory-Leibniz se basó en atan, no en 4 * atan (1) basada en la serie de Gregory-Leibniz. En otras palabras, la prueba REAL es:
sin ^ 2 x + cos ^ 2 x = 1 [Teorema] Si x = pi / 4 radianes, sin ^ 2 x = cos ^ 2 x, o sin ^ 2 x = cos ^ 2 x = 1/2.
Entonces, sen x = cos x = 1 / (raíz 2). tan x (sin x / cos x) = 1, atan x (1 / tan x) = 1.
Entonces, si atan (x) = 1, x = pi / 4 y atan (1) = pi / 4. Finalmente, 4 * atan (1) = pi)
Por favor, no me cargue con comentarios, todavía soy un preadolescente.
¿Cuál es la motivación para definir PI como
PI=4.D0*DATAN(1.D0)
dentro del código Fortran 77? Entiendo cómo funciona, pero, ¿cuál es el razonamiento?
Es porque esta es una forma exacta de calcular pi
con precisión arbitraria. Simplemente puede continuar ejecutando la función para obtener mayor precisión y detenerse en cualquier punto para tener una aproximación.
Por el contrario, especificar pi
como constante le proporciona exactamente tanta precisión como se le dio originalmente, lo que puede no ser apropiado para aplicaciones altamente científicas o matemáticas (como se usa con frecuencia Fortran).
Eso suena bastante como una solución para un error de compilación. O podría ser que este programa en particular dependa de que la identidad sea exacta, por lo que el programador lo garantizó.
Este estilo garantiza que la precisión máxima disponible en CUALQUIER arquitectura se utilice al asignar un valor a PI.
Hay más en esta pregunta que se ve a simple vista. ¿Por qué 4 arctan(1)
? ¿Por qué no otra representación como 3 arccos(1/2)
?
Esto intentará encontrar una respuesta por exclusión.
Introducción matemática: cuando se utilizan funciones trigonométricas inversas como arccos, arcsin y arctan , se puede calcular fácilmente π de varias maneras:
π = 4 arctan(1) = arccos(-1) = 2 arcsin(1) = 3 arccos(1/2) = 6 arcsin(1/2)
= 3 arcsin(sqrt(3)/2) = 4 arcsin(sqrt(2)/2) = ...
Existen muchas otras expresiones algebraicas exactas para los valores trigonométricos que podrían usarse aquí.
argumento de punto flotante 1: se entiende bien que una representación de coma flotante binaria finita no puede representar todos los números reales. Algunos ejemplos de tales números son 1/3, 0.97, π, sqrt(2), ...
Para este fin, deberíamos excluir cualquier cálculo matemático de π donde el argumento para las funciones trigonométricas inversas no pueda representarse numéricamente. Esto nos deja los argumentos -1,-1/2,0,1/2
y 1
.
π = 4 arctan(1) = 2 arcsin(1)
= 3 arccos(1/2) = 6 arcsin(1/2)
= 2 arccos(0)
= 3/2 arccos(-1/2) = -6 arcsin(-1/2)
= -4 arctan(-1) = arccos(-1) = -2 arcsin(-1)
argumento de coma flotante 2: en la representación binaria, un número se representa como 0.b n b n-1 ... b 0 x 2 m . Si la función trigonométrica inversa obtuvo la mejor aproximación binaria numérica para su argumento, no queremos perder precisión por multiplicación. Para este fin, solo deberíamos multiplicarnos con potencias de 2.
π = 4 arctan(1) = 2 arcsin(1)
= 2 arccos(0)
= -4 arctan(-1) = arccos(-1) = -2 arcsin(-1)
nota: esto es visible en la representación binary64 de IEEE-754 (forma más común de DOUBLE PRECISION
o kind=REAL64
). Ahí tenemos
write(*,''(F26.20)'') 4.0d0*atan(1.0d0) -> " 3.14159265358979311600"
write(*,''(F26.20)'') 3.0d0*acos(0.5d0) -> " 3.14159265358979356009"
Esta diferencia no está en IEEE-754 binary32 (la forma más común de REAL
o kind=REAL32
) y IEEE-754 binary128 (forma más común de kind=REAL128
)
argumento de implementación difusa: a partir de este punto, todo depende un poco de la implementación de las funciones trigonométricas inversas. A veces arccos
y arcsin
se derivan de atan2
y atan2
como
ACOS(x) = ATAN2(SQRT(1.-x*x),1)
ASIN(x) = ATAN2(1,SQRT(1.-x*x))
Además, atan2
es parte del conjunto de instrucciones x86 como FPATAN
mientras que los otros no lo son. Para este fin, yo discutiría el uso de:
π = 4 arctan(1)
sobre todos los demás.
Nota: este es un argumento difuso. Estoy seguro de que hay personas con mejores opiniones sobre esto.
El argumento de Fortran: ¿por qué deberíamos aproximarnos a π
como:
integer, parameter :: sp = selected_real_kind(6, 37)
integer, parameter :: dp = selected_real_kind(15, 307)
integer, parameter :: qp = selected_real_kind(33, 4931)
real(kind=sp), parameter :: pi_sp = 4.0_sp*atan2(1.0_sp,1.0_sp)
real(kind=dp), parameter :: pi_dp = 4.0_dp*atan2(1.0_dp,1.0_dp)
real(kind=qp), parameter :: pi_qp = 4.0_qp*atan2(1.0_qp,1.0_qp)
y no :
real(kind=sp), parameter :: pi_sp = 3.14159265358979323846264338327950288_sp
real(kind=dp), parameter :: pi_dp = 3.14159265358979323846264338327950288_dp
real(kind=qp), parameter :: pi_qp = 3.14159265358979323846264338327950288_qp
La respuesta está en el estándar Fortran . La norma nunca establece que un REAL
de ningún tipo debe representar un número de coma flotante IEEE-754 . La representación de REAL
depende del procesador. Esto implica que podría consultar selected_real_kind(33, 4931)
y esperar obtener un número de punto flotante binario128 , pero podría obtener un kind
devuelto que representa un punto flotante con una precisión mucho mayor. Tal vez 100 dígitos, quién sabe. ¡En este caso, mi cadena de números anterior es muy corta! No se puede usar this solo para estar seguro? ¡Quizás sea demasiado corto!
hecho interesante: sin(pi) is never zero
write(*,''(F17.11)'') sin(pi_sp) => " -0.00000008742"
write(*,''(F26.20)'') sin(pi_dp) => " 0.00000000000000012246"
write(*,''(F44.38)'') sin(pi_qp) => " 0.00000000000000000000000000000000008672"
que se entiende como:
pi = 4 ATAN2(1,1) = π + δ
SIN(pi) = SIN(pi - π) = SIN(δ) ≈ δ
program print_pi
! use iso_fortran_env, sp=>real32, dp=>real64, qp=>real128
integer, parameter :: sp = selected_real_kind(6, 37)
integer, parameter :: dp = selected_real_kind(15, 307)
integer, parameter :: qp = selected_real_kind(33, 4931)
real(kind=sp), parameter :: pi_sp = 3.14159265358979323846264338327950288_sp
real(kind=dp), parameter :: pi_dp = 3.14159265358979323846264338327950288_dp
real(kind=qp), parameter :: pi_qp = 3.14159265358979323846264338327950288_qp
write(*,''("SP "A17)'') "3.14159265358..."
write(*,''(F17.11)'') pi_sp
write(*,''(F17.11)'') acos(-1.0_sp)
write(*,''(F17.11)'') 2.0_sp*asin( 1.0_sp)
write(*,''(F17.11)'') 4.0_sp*atan2(1.0_sp,1.0_sp)
write(*,''(F17.11)'') 3.0_sp*acos(0.5_sp)
write(*,''(F17.11)'') 6.0_sp*asin(0.5_sp)
write(*,''("DP "A26)'') "3.14159265358979323846..."
write(*,''(F26.20)'') pi_dp
write(*,''(F26.20)'') acos(-1.0_dp)
write(*,''(F26.20)'') 2.0_dp*asin( 1.0_dp)
write(*,''(F26.20)'') 4.0_dp*atan2(1.0_dp,1.0_dp)
write(*,''(F26.20)'') 3.0_dp*acos(0.5_dp)
write(*,''(F26.20)'') 6.0_dp*asin(0.5_dp)
write(*,''("QP "A44)'') "3.14159265358979323846264338327950288419..."
write(*,''(F44.38)'') pi_qp
write(*,''(F44.38)'') acos(-1.0_qp)
write(*,''(F44.38)'') 2.0_qp*asin( 1.0_qp)
write(*,''(F44.38)'') 4.0_qp*atan2(1.0_qp,1.0_qp)
write(*,''(F44.38)'') 3.0_qp*acos(0.5_qp)
write(*,''(F44.38)'') 6.0_qp*asin(0.5_qp)
write(*,''(F17.11)'') sin(pi_sp)
write(*,''(F26.20)'') sin(pi_dp)
write(*,''(F44.38)'') sin(pi_qp)
end program print_pi
Porque Fortran no tiene una constante incorporada para PI
. Pero en lugar de ingresar el número manualmente y cometer un error potencial o no obtener la máxima precisión posible en la implementación dada, dejar que la biblioteca calcule el resultado garantiza que ninguno de esos inconvenientes ocurra.
Estos son equivalentes y a veces los verás también:
PI=DACOS(-1.D0)
PI=2.D0*DASIN(1.D0)