web-dev-qa-db-ja.com

PI = 4 * ATAN(1.d0)を定義する理由

PIを次のように定義する動機は何ですか?

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

fortran 77コード内で?私はそれがどのように機能するか理解していますが、理由は何ですか?

53
ccook

このスタイルにより、PIに値を割り当てるときに、どのアーキテクチャでも利用可能な最大精度が使用されることが保証されます。

63
John Gietzen

FortranにはPIの組み込み定数がないためです。ただし、番号を手動で入力して、特定の実装で間違いを犯したり、可能な限り最大の精度を得られない可能性があるのではなく、ライブラリに結果を計算させて、これらの欠点が発生しないことを保証します。

これらは同等であり、時々表示されることもあります。

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

これはパイの最短シリーズだからだと思います。それはまた、それが最も正確であることを意味します。

Gregory-Leibnizシリーズ(4/1-4/3 + 4/5-4/7 ...)はpiに等しい。

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

したがって、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 ...

これはグレゴリー・ライプニッツ級数に等しいため、piに等しく、約3.1415926535 8979323846 2643383279 5028841971 69399373510です。

Atanを使用してpiを見つける別の方法は次のとおりです。

pi = 16 * atan(1/5)-4 * atan(1/239)ですが、もっと複雑だと思います。

これがお役に立てば幸いです!

(正直に言うと、グレゴリー・ライプニッツシリーズはグレゴリー・ライプニッツシリーズに基づく4 * atan(1)ではなく、atanに基づいていたと思います。

sin ^ 2 x + cos ^ 2 x = 1 [定理] x = pi/4ラジアンの場合、sin ^ 2 x = cos ^ 2 x、またはsin ^ 2 x = cos ^ 2 x = 1/2。

次に、sin x = cos x = 1 /(root 2)。 tan x(sin x/cos x)= 1、atan x(1/tan x)= 1。

したがって、atan(x)= 1、x = pi/4、およびatan(1)= pi/4の場合。最後に、4 * atan(1)= pi)

コメントを私にロードしないでください-私はまだ十代前です。

13
Justin

これは、piを任意の精度で計算する正確な方法だからです。関数を実行し続けるだけで精度を高め、任意の時点で停止して近似値を得ることができます。

対照的に、piを定数として指定すると、元々与えられた精度とまったく同じ精度が得られますが、これは高度な科学的または数学的なアプリケーションには適していません(Fortranがよく使用されます)。

9
John Feminella

この質問には、目に見える以上のものがあります。なぜ4 arctan(1)?なぜ3 arccos(1/2)などの他の表現がないのですか?

これは、除外によって答えを見つけようとします。

数学的イントロ:arccos、arcsinなどの逆三角関数を使用する場合)およびarctan、さまざまな方法で簡単にπを計算できます。

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

他にも多くの 三角値の正確な代数式 が存在し、ここで使用できます。

浮動小数点引数1:有限2進浮動小数点表現all実数。そのような数の例は、1/3, 0.97, π, sqrt(2), ...です。このために、逆三角関数の引数を数値で表現できない場合のπの数学計算をexcludeする必要があります。これにより、引数_-1,-1/2,0,1/2_および_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)
_

浮動小数点引数2:バイナリ表現では、数値は0.bとして表されますnbn-1... b x 2m。逆三角関数がその引数に最適な数値バイナリ近似を考え出した場合、乗算によって精度を失いたくありません。このため、2の累乗で乗算する必要があります。

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

note:これは IEEE-754 binary64 表現(_DOUBLE PRECISION_または_kind=REAL64_の最も一般的な形式)で表示されます。そこにある

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

IEEE-754 binary32REALまたは_kind=REAL32_の最も一般的な形式)および IEEE-754 binary128 (ほとんど_kind=REAL128_)の一般的な形式

ファジー実装引数:この点から、すべては逆三角関数の実装に少し依存します。時々arccosおよびarcsinは、_atan2_および_atan2_から派生します。

_ACOS(x) = ATAN2(SQRT(1-x*x),1)
ASIN(x) = ATAN2(1,SQRT(1-x*x))
_

より具体的には数値の観点から:

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

さらに、_atan2_は x86命令セットFPATAN の一部ですが、その他はそうではありません。この目的のために、私は以下の使用法について議論します。

_π = 4 arctan(1)
_

他のすべての上。

注:これはあいまいな引数です。私はこれについてより良い意見を持つ人々がいると確信しています。

Fortran引数:なぜ_π_を近似する必要があるのか​​:

_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)
_

ではなく:

_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
_

答えは Fortran標準 にあります。標準neverは、あらゆる種類のREALIEEE-754浮動小数点数 を表す必要があると述べています。 REALの表現はプロセッサに依存します。これは、selected_real_kind(33, 4931)を照会して binary128浮動小数点数 を取得することを期待できることを意味しますが、はるかに高い浮動小数点を表すkindが返される場合があります正確さ。たぶん、100桁でしょう。この場合、上記の数字の列は短くなります! this を使用することはできませんか?そのファイルでも短すぎる可能性があります!

興味深い事実: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"
_

次のように理解されます:

_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
_
4
kvantour