Обчислення значення PI є однією зі складної проблеми, і wikipedia розповідає про наближення, зроблені для цього, і каже, що важко точно розрахувати PI.
Як C обчислює PI? Чи обчислює це кожен раз, чи використовує менш точну фіксовану величину?
Обчислення значення PI є однією зі складної проблеми, і wikipedia розповідає про наближення, зроблені для цього, і каже, що важко точно розрахувати PI.
Як C обчислює PI? Чи обчислює це кожен раз, чи використовує менш точну фіксовану величину?
Відповіді:
У C Pi визначається в math.h: #define M_PI 3.14159265358979323846
PIв <math.h>. POSIX визначає M_PI, але знову ж таки, відповідна реалізація C може не визначити його. (POSIX накладає деякі вимоги, що суперечать стандарту C.) Але ви можете визначити це таким чином у власній програмі.
M_. Були також такі речі , як M_E, і M_LN10т.д. Вони ніколи не зробили це до стандарту.
Найближче, що C робить до "обчислення π" способом, який безпосередньо видно програмам, є acos(-1)подібним. Це майже завжди робиться з поліноміальними / раціональними наближеннями для функції, що обчислюється (або в C, або за допомогою мікрокоду FPU).
Тим НЕ менше, цікаве питання полягає в тому , що обчислення тригонометричних функцій ( sin, cosі tan) вимагає скорочення їх аргументу по модулю 2л. Оскільки 2π не є діадичним раціональним (і навіть не раціональним), його неможливо представити в будь-якому типі з плаваючою комою, і, отже, використання будь-якого наближення значення призведе до катастрофічного накопичення помилок для великих аргументів (наприклад, якщо xє 1e12, і 2*M_PIвідрізняється від 2π на ε, тоді fmod(x,2*M_PI)відрізняється від правильного значення 2π до 1e12 * ε / π, помноженого на правильне значення xмода 2π. Тобто це абсолютно безглуздо.
Правильна реалізація стандартної математичної бібліотеки C просто має гігантське дуже високоточне подання π, закодованого у своєму джерелі, для вирішення проблеми коректного скорочення аргументів (і використовує деякі химерні прийоми, щоб зробити це не зовсім таким гігантським ). Це , як більшість / всі версії C про sin/ cos/ tanфункціях роботи. Однак відомо, що деякі реалізації (наприклад, glibc) використовують реалізації збірки на деяких процесорах (наприклад, x86) і не виконують коректного скорочення аргументів, що призводить до абсолютно безглуздих результатів. (До речі, неправильний asm зазвичай працює приблизно з такою ж швидкістю, як і правильний код C для невеликих аргументів.)
xмайже безглуздо і, швидше за все, помилка в коді, що використовує функцію синуса. Якщо xвоно настільки велике, що стає цілим числом, тоді ви можете представити лише близько 6 значень xза період синуса. Звичайно, можна знайти такий, yякий відповідає умові, і це приємно, але я сумніваюся, що існує якийсь корисний додаток для обчислення синусів цілих чисел.
xбув би аналіз того, як швидко зростає ця "помилка епсилону" x. Якщо є суттєва помилка 1000*M_PI, тоді я розумію проблему і від усього серця погоджуюсь з вами.
fmod(x,2*M_PI)проти правильного значення, зменшеного аргументом, зростає лінійно за величиною x. Отже, припускаючи, що 1ulp знаходиться xбезпосередньо поза одиничним колом, ви розглядаєте щось на зразок 1000ulp 1000*M_PI. Поблизу нулів sinблизький до лінійного з нахилом 1, тому # ulp в аргументі переводиться безпосередньо до ulp в результаті.
sin(2^n)для великих значень n; Однак я не пам’ятаю, що вони зараз.
Просто визначте:
#define M_PI acos(-1.0)
Він повинен дати вам точний номер PI, з яким працюють математичні функції. Отже, якщо вони змінюють значення PI, з яким працюють, по тангенсу, косинусу чи синусу, тоді ваша програма повинна бути завжди оновленою;)
acosФункція є частиною мови C правильного.
у будь-якому випадку у вас не необмежена точність, тому C визначає константу таким чином:
#define PI 3.14159265358979323846
import math.h, щоб використовувати це
M_PIнемає в C. Це частина опції розширення XSI в POSIX.
Залежно від бібліотеки, якою ви використовуєте стандартні попередньо визначені математичні константи GNU C, тут ... https://www.gnu.org/software/libc/manual/html_node/Mathematical-Constants.html
Вони у вас уже є, то навіщо їх перевизначати? Можливо, у ваших системних настільних калькуляторах вони є ще більш точними, щоб ви могли, але просто переконайтеся, що не суперечите існуючим визначеним, щоб заощадити на попередженнях компіляції, оскільки вони, як правило, отримують за замовчуванням подібні речі. Насолоджуйтесь!
Я не знаю точно , як Cрозраховує PIбезпосередньо , як я більше знайомий з C++чим C; однак ви можете мати заздалегідь визначений C macroабо constтакий, як:
#define PI 3.14159265359.....
const float PI = 3.14159265359.....
const double PI = 3.14159265359.....
/* If your machine,os & compiler supports the long double */
const long double PI = 3.14159265359.....
або ви можете обчислити його за допомогою будь-якої з цих двох формул:
#define M_PI acos(-1.0);
#define M_PI (4.0 * atan(1.0)); // tan(pi/4) = 1 or acos(-1)
Я не впевнений на 100%, але думаю, що atan()це дешевше acos().
#define CONSTANT numberHere?
Cдуже іржава, оскільки минуло близько 20 років, відколи я працюю в ній, і той факт, що я в основному використовую C++. Я спочатку відповідав на це запитання з урахуванням C++перспективи ... Я оновив відповідь, щоб відповісти на це ...
double) має бути достатньо для обчислення діаметра Сонячної системи з похибкою менше ширини волосся.