Saya ingin menggunakan fungsi konstanta PI dan trigonometri dalam beberapa program C ++. Saya mendapatkan fungsi trigonometri dengan include <math.h>
. Namun, sepertinya tidak ada definisi untuk PI dalam file header ini.
Bagaimana saya bisa mendapatkan PI tanpa mendefinisikannya secara manual?
c++
trigonometry
Etan
sumber
sumber
3.14
,3.141592
danatan(1) * 4
?Jawaban:
Pada beberapa platform (terutama yang lebih tua) (lihat komentar di bawah), Anda mungkin perlu melakukannya
dan kemudian sertakan file header yang diperlukan:
dan nilai pi dapat diakses melalui:
Dalam
math.h
(2014) saya ini didefinisikan sebagai:tetapi periksa
math.h
lebih lanjut. Ekstrak dari "lama"math.h
(tahun 2009):Namun:
pada platform yang lebih baru (setidaknya pada 64 bit Ubuntu 14.04 saya) saya tidak perlu mendefinisikan
_USE_MATH_DEFINES
Pada platform Linux (baru-baru ini) ada
long double
nilai - nilai yang juga disediakan sebagai Ekstensi GNU:sumber
#define _USE_MATH_DEFINES
diikuti oleh#include <math.h>
mendefinisikanM_PI
dalam visual c ++. Terima kasih.cmath
bukanmath.h
._USE_MATH_DEFINES
apakah GCC mengeluh karena__STRICT_ANSI__
itu didefinisikan (mungkin Anda lulus-pedantic
atau-std=c++11
) yang tidakM_PI
dapat didefinisikan, maka tentukan dengan-D__STRICT_ANSI__
. Saat mendefinisikannya sendiri, karena itu C ++, alih-alih makro, Anda seharusnyaconstexpr auto M_PI = 3.14159265358979323846;
.Pi dapat dihitung sebagai
atan(1)*4
. Anda bisa menghitung nilainya dengan cara ini dan menyimpannya.sumber
constexpr double pi() { return std::atan(1)*4; }
atan(1)*4 == 3.141592653589793238462643383279502884
(secara kasar). Saya tidak akan bertaruh. Normal dan gunakan literal mentah untuk mendefinisikan konstanta. Mengapa kehilangan presisi padahal Anda tidak perlu melakukannya?atan2(0, -1);
.atan
tidakconstexpr
.acos(-1)
saja, tidak perluatan2
.Anda juga bisa menggunakan boost, yang mendefinisikan konstanta matematika penting dengan akurasi maksimum untuk tipe yang diminta (yaitu float vs double).
Lihat dokumentasi peningkatan untuk lebih banyak contoh.
sumber
not gonna use libs
itu hama dan mungkin alasan nomor satu untuk perangkat lunak buruk yang ditulis dalam bahasa C ++.Alih-alih mendapatkannya dari unit FPU pada chip:
sumber
Saya akan merekomendasikan hanya mengetik pi ke presisi yang Anda butuhkan. Ini tidak akan menambah waktu kalkulasi untuk eksekusi Anda, dan ini akan portabel tanpa menggunakan header atau #define. Menghitung Acos atau Atan selalu lebih mahal daripada menggunakan nilai yang telah dihitung.
sumber
const
aconstexpr
.constexpr
.Daripada menulis
Saya akan merekomendasikan menggunakan
-D_USE_MATH_DEFINES
atau/D_USE_MATH_DEFINES
bergantung pada kompiler Anda.Dengan cara ini Anda yakin bahwa bahkan dalam hal seseorang termasuk tajuk sebelum Anda melakukannya (dan tanpa #define) Anda masih akan memiliki konstanta alih-alih kesalahan kompiler yang tidak jelas yang perlu waktu lama untuk dilacak.
sumber
<cmath>
di tempat yang berbeda itu menjadi masalah besar (terutama jika disertakan oleh perpustakaan lain Anda termasuk). Akan jauh lebih baik jika mereka menempatkan bagian itu di luar penjaga sundulan tetapi juga tidak bisa berbuat banyak tentang itu sekarang. Direktif kompiler bekerja dengan sangat baik.Karena pustaka standar resmi tidak mendefinisikan PI konstan, Anda harus mendefinisikannya sendiri. Jadi jawaban untuk pertanyaan Anda "Bagaimana saya bisa mendapatkan PI tanpa mendefinisikannya secara manual?" adalah "Anda tidak - atau Anda mengandalkan beberapa ekstensi khusus-kompiler.". Jika Anda tidak khawatir tentang portabilitas Anda dapat memeriksa manual kompiler Anda untuk ini.
C ++ memungkinkan Anda untuk menulis
tetapi inisialisasi konstanta ini tidak dijamin statis. Namun kompiler G ++ menangani fungsi matematika tersebut sebagai intrinsik dan mampu menghitung ekspresi konstan ini pada waktu kompilasi.
sumber
4*atan(1.)
:atan
mudah diimplementasikan dan dikalikan dengan 4 adalah operasi yang tepat. Tentu saja, kompiler modern melipat (bertujuan untuk melipat) semua konstanta dengan presisi yang diperlukan, dan sangat masuk akal untuk menggunakanacos(-1)
atau bahkanstd::abs(std::arg(std::complex<double>(-1.,0.)))
yang merupakan kebalikan dari formula Euler dan dengan demikian lebih estetis daripada yang terlihat (saya menambahkanabs
karena saya tidak t ingat bagaimana pesawat kompleks dipotong atau jika itu didefinisikan sama sekali).Dari halaman manual Posix di math.h :
sumber
C ++ 20
std::numbers::pi
Akhirnya, sudah tiba: http://eel.is/c++draft/numbers
Saya berharap penggunaannya menjadi seperti:
Saya akan mencobanya ketika dukungan datang ke GCC, GCC 9.1.0 dengan
g++-9 -std=c++2a
masih tidak mendukungnya.Proposal yang diterima menjelaskan:
Ada juga
std::numbers::e
tentu saja :-) Bagaimana cara menghitung konstanta Euler atau bertenaga Euler di C ++?Konstanta ini menggunakan fitur templat variabel C ++ 14 : C ++ 14 Templat Variabel: apa tujuannya? Adakah contoh penggunaan?
Dalam versi draft sebelumnya, konstanta berada di bawah
std::math::pi
: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdfsumber
Standar C ++ tidak memiliki konstanta untuk PI.
Banyak C ++ compiler menentukan
M_PI
dicmath
(atau dimath.h
C) sebagai ekstensi non-standar. Anda mungkin harus#define _USE_MATH_DEFINES
sebelum dapat melihatnya.sumber
Saya akan lakukan
atau
Saya tidak akan mengetikkan π dengan presisi yang Anda butuhkan . Apa artinya itu? The presisi yang Anda butuhkan adalah ketepatan
T
, tapi kita tahu apa-apa tentangT
.Anda mungkin berkata: Apa yang sedang Anda bicarakan?
T
akanfloat
,double
ataulong double
. Jadi, ketikkan saja ketepatannyalong double
, yaituTapi apakah Anda benar-benar tahu bahwa tidak akan ada tipe floating point baru dalam standar di masa depan dengan presisi yang lebih tinggi daripada
long double
? Kamu tidak.Dan itulah mengapa solusi pertama itu indah. Anda dapat yakin bahwa standar akan membebani fungsi trigonometri untuk tipe baru.
Dan tolong, jangan katakan bahwa evaluasi fungsi trigonometri pada inisialisasi adalah penalti kinerja.
sumber
arg(log(x)) == π
untuk semua0 < x < 1
.Saya menggunakan berikut ini di salah satu header umum saya di proyek yang mencakup semua pangkalan:
Di samping catatan, semua kompiler di bawah ini mendefinisikan konstanta M_PI dan M_PIl jika Anda menyertakan
<cmath>
. Tidak perlu menambahkan `#define _USE_MATH_DEFINES yang hanya diperlukan untuk VC ++.sumber
M_PI
tanpa perlu_USE_MATH_DEFINES
Saya biasanya lebih suka mendefinisikan sendiri:
const double PI = 2*acos(0.0);
karena tidak semua implementasi menyediakannya untuk Anda.Pertanyaan apakah fungsi ini dipanggil pada saat runtime atau statis pada saat kompilasi biasanya tidak menjadi masalah, karena itu hanya terjadi sekali saja.
sumber
double x = pi * 1.5;
dan sejenisnya). Jika Anda pernah berniat untuk menggunakan PI dalam matematika renyah dalam loop ketat, Anda lebih baik memastikan nilainya diketahui oleh kompiler.Saya baru saja menemukan artikel ini oleh Danny Kalev yang memiliki tip bagus untuk C ++ 14 ke atas.
Saya pikir ini cukup keren (walaupun saya akan menggunakan PI presisi tertinggi di sana saya bisa), terutama karena template dapat menggunakannya berdasarkan jenis.
sumber
Nilai-nilai seperti M_PI, M_PI_2, M_PI_4, dll bukan standar C ++ sehingga constexpr tampaknya merupakan solusi yang lebih baik. Ekspresi const yang berbeda dapat dirumuskan yang menghitung pi yang sama dan itu menyangkut saya apakah mereka (semua) memberikan saya akurasi penuh. Standar C ++ tidak secara eksplisit menyebutkan cara menghitung pi. Karena itu, saya cenderung kembali ke mendefinisikan pi secara manual. Saya ingin berbagi solusi di bawah ini yang mendukung semua jenis fraksi pi dalam akurasi penuh.
sumber
Pada windows (cygwin + g ++), saya merasa perlu menambahkan flag
-D_XOPEN_SOURCE=500
untuk preprocessor untuk memproses definisiM_PI
inmath.h
.sumber
M_PI
bekerja pada platform tertentu. Itu bukan komentar pada jawaban untuk beberapa platform lain lagi bahwa jawaban untuk beberapa platform lain adalah komentar untuk yang satu ini.C ++ 14 memungkinkan Anda melakukannya
static constexpr auto pi = acos(-1);
sumber
std::acos
bukan aconstexpr
. Jadi, kode Anda tidak akan dikompilasi.acos
tidakconstexpr
dalam C ++ 14, dan tidak diusulkan untuk menjadiconstexpr
bahkan di C ++ 17constexpr
? Rupanya tidak: stackoverflow.com/questions/17347935/constexpr-math-functionsconstexpr
, lihat misalnya ( github.com/kthohr/gcem ). Tetapi mereka tidak kompatibel dengan fungsi C dari nama yang sama, sehingga mereka tidak dapat mengambil alih nama lama.Beberapa solusi elegan. Saya ragu bahwa ketepatan fungsi trigonometri sama dengan ketepatan jenis. Bagi mereka yang lebih suka menulis nilai konstan, ini berfungsi untuk g ++: -
Keakuratan 256 desimal digit harus cukup untuk jenis ganda panjang di masa mendatang. Jika diperlukan, kunjungi https://www.piday.org/million/ .
sumber
sumber
Kamu bisa melakukan ini:
Jika
M_PI
sudah didefinisikan dalamcmath
, ini tidak akan melakukan apa pun selain memasukkancmath
. JikaM_PI
tidak didefinisikan (yang merupakan kasus misalnya di Visual Studio), itu akan mendefinisikannya. Dalam kedua kasus, Anda dapat menggunakanM_PI
untuk mendapatkan nilai pi.Nilai pi ini berasal dari qmath.h Qt Creator.
sumber
Anda bisa menggunakannya:
Konstanta Matematika tidak didefinisikan dalam Standar C / C ++. Untuk menggunakannya, Anda harus terlebih dahulu mendefinisikan
_USE_MATH_DEFINES
dan kemudian memasukkancmath
ataumath.h
.sumber