6 ответов:
этот стиль гарантирует, что максимальная точность, доступная на любой архитектуре, используется при присвоении значения PI.
потому что Fortran не имеет встроенной константы для
PI. Но вместо того, чтобы вводить число вручную и потенциально делать ошибку или не получать максимально возможную точность в данной реализации, позволяя библиотеке вычислить результат для вас, гарантирует, что ни один из этих недостатков не произойдет.они эквивалентны, и вы иногда будете видеть их тоже:
PI=DACOS(-1.D0) PI=2.D0*DASIN(1.D0)
Я считаю, что это потому, что это самая короткая серия на pi. Это также означает, что он самый точный.
Грегори-Лейбница серии (4/1 - 4/3 + 4/5 - 4/7...) равно Пи.
atan (x) = x^1/1 - x^3/3 + x^5/5 - x^7/7...
Так, Атан(1) = 1/1 - 1/3 + 1/5 - 1/7 + 1/9... 4 * Атан(1) = 4/1 - 4/3 + 4/5 - 4/7 + 4/9...
что равно ряду Грегори-Лейбница, и поэтому равно pi, приблизительно 3.1415926535 8979323846 2643383279 5028841971 69399373510.
другой способ использовать atan и найти pi:
Пи = 16*Атан(1/5) - 4*Атан(1/239), но я думаю, что это сложнее.
надеюсь, это поможет!
(честно говоря, я думаю, что серия Григория-Лейбница была основана на atan, а не 4*atan(1), основанный на серии Григория-Лейбница. Другими словами, реальное доказательство:
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 / (корень 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.)
пожалуйста, не загружайте меня комментариями-я все еще подросток.
Это потому, что это точный способ вычисления
piс произвольной точностью. Вы можете просто продолжить выполнение функции, чтобы получить все большую и большую точность и остановиться в любой точке, чтобы иметь приближение.напротив, задание
piкак константа предоставляет вам ровно столько точности, сколько было первоначально дано, что может не подходить для высоконаучных или математических приложений (как часто используется Fortran).
в этом вопросе есть больше, чем кажется на первый взгляд. Почему
4 arctan(1)? Почему бы не любое другое представление, такое как3 arccos(1/2)?это будет пытаться найти ответ путем исключения.
математические интро: при использовании обратные тригонометрические функции например arccos, arcsin и равенства arctg, можно легко вычислить π различными способами:
π = 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: хорошо понятно, что а конечное двоичное представление с плавающей точкой не может представлять все реальные цифры. Некоторые примеры таких чисел
1/3, 0.97, π, sqrt(2), .... С этой целью мы должны исключить любое математическое вычисление π, где аргумент обратных тригонометрических функций не может быть представлен численно. Это оставляет нам аргументы-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.bnbn-1...b0 x 2m. Если обратная тригонометрическая функция придумала лучшее числовое двоичное приближение для своего аргумента, мы не хотим терять точность умножения. С этой целью мы должны только умножьте со степенями 2.
π = 4 arctan(1) = 2 arcsin(1) = 2 arccos(0) = -4 arctan(-1) = arccos(-1) = -2 arcsin(-1)Примечание: это видно в 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 binary32 (наиболее распространенная форма
REALили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)за все остальные.
Примечание: это нечеткий аргумент. Я уверен, что есть люди с лучшим мнением об этом.
аргумент Фортран: почему мы должны приблизительные
πкак :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 standard. Стандартный никогда утверждает, что a
REALлюбой вид должен представлять собой IEEE-754 с плавающей точкой номер. ПредставлениеREALзависит от процессора. Это означает, что я мог бы спроситьselected_real_kind(33, 4931)и ожидать, чтобы получить binary128 число с плавающей запятой, но я мог бы получитьkindвозвращается, что представляет собой плавающую точку с гораздо более высокой точностью. Может быть, 100 цифр, кто знает. В этом случае моя вышеприведенная строка чисел должна быть короткой! Нельзя использовать этой просто чтобы быть уверенным? Даже этот файл может быть слишком коротко!интересный факт :
sin(pi) is never zerowrite(*,'(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
Это звучит очень похоже на обходной путь для ошибки компилятора. Или может быть, что эта конкретная программа зависит от того, что идентичность является точной, и поэтому программист сделал это гарантированным.
Comments