Question

Quelle est la motivation pour définir PI comme

PI=4.D0*DATAN(1.D0)

du code Fortran 77? Je comprends comment cela fonctionne, mais quel est le raisonnement?

Était-ce utile?

La solution

Ce style garantit que la précision maximale disponible sur toute architecture est utilisée lors de l'attribution d'une valeur à PI.

Autres conseils

Parce que Fortran ne dispose pas d'une constante intégrée pour PI. Mais plutôt que de taper le numéro manuellement et faisant potentiellement une erreur ou ne pas obtenir la précision maximale possible sur la mise en œuvre donnée, laissant la bibliothèque calculer le résultat pour vous garantit qu'aucun de ces inconvénients se produisent.

Ce sont équivalentes et vous verrez parfois les voir aussi:

PI=DACOS(-1.D0)
PI=2.D0*DASIN(1.D0)

Je crois qu'il est parce que c'est la série la plus courte sur pi. Cela signifie aussi qu'il est le plus précis.

La série Gregory-Leibniz (04.01 à 04.03 + 04.05 au 04.07 ...). Pi est égal à

atan (x) = x ^ 1/1 - x ^ 3/3 + x ^ 5/5 - x ^ 7/7 ...

Alors, atan (1) = 01/01 au 01/03 + 01/05 au 01/07 + 1/9 ... 4 * atan (1) = 4.1 à 4.3 + 4/5 à 4/7 + 4/9 ...

Cela correspond à la série Gregory-Leibniz, et est donc égale à pi, environ 3,1415926535 8979323846 2643383279 5028841971 69399373510.

Une autre façon d'utiliser atan et trouver pi est:

pi = 16 * atan (1/5) - 4 * atan (1/239), mais je pense que c'est plus compliqué

.

J'espère que cela aide!

(Pour être honnête, je pense que la série Gregory-Leibniz était basée sur atan, pas 4 * atan (1) basé sur la série Gregory-Leibniz En d'autres termes, la preuve est REAL:.

sin ^ 2 x + cos ^ 2 = x 1 [Théorème] Si x = pi / 4 radians, sin ^ cos 2 x = ^ 2 X ou sin ^ 2 = x cos ^ 2 x = 1/2.

Ensuite, sin x = cos x = 1 / (racine de 2). tan x (sin x / cos x) = 1, x atan (1 / tan x) = 1.

Si atan (x) = 1, x = pi / 4, et atan (1) = pi / 4. Enfin, 4 * atan (1) = pi.)

S'il vous plaît ne me charge pas avec des commentaires, je suis encore un pré-ado.

Il est parce que c'est une façon exacte de calculer pi à la précision arbitraire. Vous pouvez simplement continuer à exécuter la fonction pour obtenir une plus grande et une plus grande précision et arrêter à tout moment d'avoir une approximation.

Par contre, en spécifiant pi comme une constante vous fournit exactement autant de précision que l'origine donné, ce qui peut ne pas être approprié pour les applications hautement scientifiques ou mathématiques (comme Fortran est souvent utilisé avec).

Il y a plus à cette question que rencontre l'oeil. Pourquoi 4 arctan(1)? Pourquoi aucune autre représentation, comme 3 arccos(1/2)?

va essayer de trouver une réponse par l'exclusion.

introduction mathématique: Lorsque vous utilisez inverses des fonctions trigonométriques comme arccos, arcsin et arctan , on peut facilement calculer π de diverses manières:

π = 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) = ...

Il existe beaucoup d'autres expressions algébriques exactes pour les valeurs trigonométriques qui pourrait être utilisé ici.

argument en virgule flottante 1: il est bien entendu que représentation binaire en virgule flottante finie ne peut pas représenter tous les nombres réels . Quelques exemples de ces chiffres sont 1/3, 0.97, π, sqrt(2), .... À cette fin, nous devrions exclure tout calcul mathématique de π où l'argument des fonctions trigonométriques inverses ne peut pas être représentée numériquement. Cela nous laisse les arguments -1,-1/2,0,1/2 et 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)

argument à virgule flottante 2: dans la représentation binaire, un numéro est représenté par 0.b n b n-1 ... b 0 x 2 m . Si la fonction trigonométrique inverse est arrivé avec la meilleure approximation binaire numérique pour son argument, nous ne voulons pas perdre la précision par multiplication. À cette fin, nous ne devons multiplier avec des puissances de 2.

π = 4 arctan(1) = 2 arcsin(1)
  = 2 arccos(0)
  = -4 arctan(-1) = arccos(-1) = -2 arcsin(-1)

Note: Ceci est visible dans le IEEE-754 la représentation des binary64 (la forme la plus commune de DOUBLE PRECISION ou kind=REAL64). Nous avons là

write(*,'(F26.20)') 4.0d0*atan(1.0d0) -> "    3.14159265358979311600"
write(*,'(F26.20)') 3.0d0*acos(0.5d0) -> "    3.14159265358979356009"

Cette différence n'est pas là dans IEEE-754 binary32 (le plus forme commune de REAL ou kind=REAL32) et IEEE-754 binary128 (le plus courant sous forme de kind=REAL128)

l'argument de mise en œuvre floue: à partir de ce point, tout dépend un peu sur la mise en œuvre des fonctions trigonométriques inverses. Parfois, arccos et arcsin proviennent de atan2 et atan2 comme

ACOS(x) = ATAN2(SQRT(1-x*x),1)
ASIN(x) = ATAN2(1,SQRT(1-x*x))

ou plus précisément d'un point de vue numérique:

ACOS(x) = ATAN2(SQRT((1+x)*(1-x)),1)
ASIN(x) = ATAN2(1,SQRT((1+x)*(1-x)))

En outre, atan2 fait partie du x86 Jeu d'instructions comme FPATAN tandis que les autres ne sont pas. À cette fin, je dirais l'utilisation de:

π = 4 arctan(1)

sur tous les autres.

Note: c'est un argument floue. Je suis certain qu'il ya des gens avec de meilleures opinions sur ce sujet.

L'argument Fortran: pourquoi devrions-nous π approximative:

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)

et non:

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 réponse réside dans le Fortran norme . La norme jamais indique qu'un REAL de quelque nature que devrait représenter un IEEE-754 numéro virgule flottante . La représentation de REAL dépend processeur. Cela implique que je pouvais demander selected_real_kind(33, 4931) et espérer obtenir un binary128 nombre à virgule flottante , mais je pourrais obtenir un kind revenu qui représente un point flottant avec une précision beaucoup plus élevée. Peut-être 100 chiffres, qui sait. Dans ce cas, ma chaîne au-dessus des chiffres est à court! On ne peut pas utiliser cette juste pour être sûr? Même ce fichier pourrait être trop court!

fait intéressant: 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"

qui est compris comme:

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

Cela semble beaucoup comme un travail autour d'un bug du compilateur. Ou il se pourrait que ce programme dépend de cette identité étant exacte, et que le programmeur fait garanti.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top