Ada masalah yang agak konyol dengan angka pi dalam C dan C ++. Sejauh yang saya tahu M_PI
didefinisikan dalam math.h
tidak diperlukan oleh standar apa pun.
Standar C ++ baru memperkenalkan banyak matematika yang rumit di perpustakaan standar - fungsi hiperbolik, std::hermite
dan std::cyl_bessel_i
, generator bilangan acak yang berbeda dan seterusnya dan seterusnya.
Apakah ada standar 'baru' yang memberikan konstanta untuk pi? Jika tidak - mengapa? Bagaimana semua matematika rumit ini bekerja tanpanya?
Saya menyadari pertanyaan serupa tentang pi dalam C ++ (mereka beberapa tahun dan standar lama); Saya ingin mengetahui kondisi masalah saat ini.
Saya juga sangat tertarik pada mengapa oh mengapa C ++ masih tidak memiliki pi konstan tetapi memiliki banyak matematika yang lebih rumit.
UPD: Saya tahu bahwa saya dapat mendefinisikan pi sendiri sebagai 4 * atan (1) atau acos (1) atau double pi = 3.14. Tentu. Tetapi mengapa pada tahun 2018 saya masih harus melakukannya? Bagaimana cara kerja fungsi matematika standar tanpa pi?
UPD2: Menurut laporan perjalanan ini untuk pertemuan Komite C ++ pada bulan Juli 2019 di Cologne, proposal P0631 (konstanta matematika) diterima ke dalam C ++ 20. Jadi sepertinya pada akhirnya kita akan memiliki nomor pi di perpustakaan standar!
Jawaban:
Hingga dan termasuk C ++ 17 pi bukan konstanta yang diperkenalkan ke dalam bahasa, dan itu menyakitkan di leher.
Saya beruntung karena saya menggunakan boost dan mereka mendefinisikan pi dengan jumlah desimal yang cukup besar bahkan untuk 128 bit
long double
.Jika Anda tidak menggunakan Boost maka hardcode sendiri. Mendefinisikannya dengan fungsi trigonometri memang menggoda, tetapi jika Anda melakukannya, Anda tidak dapat membuatnya
constexpr
. Keakuratan fungsi trigonometri juga tidak dijamin oleh standar apa pun yang saya tahu ( lih .std::sqrt
), Jadi Anda benar-benar berada di tanah berbahaya memang mengandalkan fungsi tersebut.Ada cara untuk mendapatkan
constexpr
nilai untuk pi menggunakan metaprogramming: lihat http://timmurphy.org/2013/06/27/template-metaprogramming-in-c/Dari C ++ 20 beberapa kabar baik. Ada adalah sebuah defininition untuk pi . C ++ 20 menambahkan beberapa konstanta matematika di
<numbers>
. Misalnyastd::numbers::pi
adalahdouble
tipe.Referensi: https://en.cppreference.com/w/cpp/numeric/constants
sumber
constexpr
sayangnya, itulah sebabnya saya mengatakan "Mendefinisikannya dengan fungsi trigonometri adalah menyusahkan"double
(atau beberapa nomor konyol jika Anda peduli tentang ganda sangat lama hipotetis).fsin
instruksi "sekitar 1,37 trilyun unit di tempat terakhir, meninggalkan kurang dari empat bit yang benar" , dan itu bahkan lebih buruk untuk input besar di mana pengurangan kisaran membungkus beberapa kali. Ini agak tangensial untuk konstanta yang digunakanlong double
dalam C ++, tetapi tetap rapi.Seperti yang orang lain katakan tidak ada
std::pi
tetapi jika Anda menginginkanPI
nilai yang tepat Anda dapat menggunakan:Ini mengasumsikan bahwa implementasi C ++ Anda menghasilkan nilai PI yang dibulatkan dengan benar
acos(-1.0)
, yang umum tetapi tidak dijamin .Tidak
constexpr
, tetapi dalam praktiknya mengoptimalkan kompiler seperti gcc dan dentang mengevaluasinya pada waktu kompilasi. Menyatakanconst
penting bagi pengoptimal untuk melakukan pekerjaan dengan baik.sumber
acos()
fungsinya memiliki kemiringan tak terbatas padax = -1
. Akibatnya, metode ini bergantung padaacos()
implementasi untuk secara mendasar menangkap kasus-1
argumen yang tepat , dan mengembalikan konstanta yang benar secara langsung. Lebih baik menggunakan sesuatu seperti4*atan(1)
yang secara matematis jauh lebih kuat (kemiringan yang berperilaku baik padax = 1
dan perkalian dengan 4 selalu tepat dengan matematika floating point).std::acos
dalam ekspresi konstan. dentang melaporkan ini sebagai kesalahan. Harap perhatikan bahwa ini adalah ekstensi yang tidak sesuai dan pada akhirnya harus diperbaiki dalam gcc. Silakan merujuk ke jawaban ini untuk lebih jelasnya.Hingga C ++ 20, tidak, tidak ada standar yang memperkenalkan konstanta yang akan mewakili angka pi (π). Anda dapat memperkirakan angka dalam kode Anda:
Bahasa lain seperti C # memiliki konstanta yang dideklarasikan di perpustakaan mereka.
Pembaruan: Dimulai dengan C ++ 20, memang ada
pi
konstanta yang dideklarasikan di dalam<numbers>
header. Hal ini diakses melalui:std::numbers::pi
.sumber
inline
untuk C ++ 17+.double
. C # membuatnya mudah karenadouble
jenisnya sudah diperbaiki. Jika saya berada di komite standar C ++ saya akan mengusulkan sesuatu sepertistd::constants<double>::pi
std::numeric_limits<double>::is_iec559;
dalam kasus itu. Saya akui, itulah yang saya miliki di "header utama" saya. Perhatikan bahwa secara formal Anda perlu memeriksa semua jenis floating point secara terpisah. Hanya karena satu adalah IEEE754 tidak berarti semuanya.M_PI
didefinisikan oleh "standar", jika bukan standar bahasa : POSIX dengan ekstensi Antarmuka Sistem X / Terbuka (yang sangat umum didukung dan diperlukan untuk pencitraan merek UNIX resmi).Ini (masih) tidak pasti apa yang akan ada di C ++ 20, tetapi karena Anda bertanya: mungkin akan memiliki konstanta seperti itu . Makalah ini digabungkan dalam putaran terakhir fitur C ++ 20 (untuk Draft Komite pada Agustus 2019).
Secara khusus, akan ada
std::numbers::pi
(tipedouble
) dan templat variabel yang dapat Anda gunakan jika Anda menginginkan jenis titik apung yang berbeda, misalnyastd::numbers::pi_v<float>
. Daftar konstanta lengkap dapat dilihat di [number.syn] .sumber
Ini jelas bukan ide yang baik karena tidak ada tipe yang jelas yang mendefinisikan pi yang berlaku secara universal di seluruh domain.
Pi, tentu saja, bilangan irasional sehingga tidak dapat dengan tepat diwakili oleh tipe C ++ apa pun . Anda mungkin berpendapat bahwa pendekatan alami, oleh karena itu, adalah untuk mendefinisikannya dalam tipe floating point terbesar yang tersedia. Namun, ukuran tipe floating point standar terbesar
long double
tidak ditentukan oleh standar C ++ sehingga nilai konstanta akan bervariasi di antara sistem. Lebih buruk lagi, untuk program apa pun yang jenis kerjanya bukan tipe terbesar ini, definisi pi akan menjadi tidak tepat karena akan membebankan biaya kinerja pada setiap penggunaan pi.Hal ini juga sepele bagi programmer mana pun untuk menemukan nilai pi dan mendefinisikan konstanta mereka sendiri yang cocok untuk digunakan, sehingga tidak memberikan keuntungan besar untuk memasukkannya dalam header matematika.
sumber
pi
konstanta polimorfik adalah jalur yang jelas ke depan - dalam bahasa dengan inferensi tipe Hindley-Milner. Di Haskell, kita selalu memilikinyapi :: Floating a => a
, sehinggapi
secara otomatis akan memiliki nilai3.1415927
dalamFloat
konteks,3.141592653589793
dalamDouble
konteks, danπ
dalam konteks komputasi-simbolik. Tetapi apakah orang benar-benar ingin secara eksplisit membuat parameter template? Tampak agak canggung, terutama jikalong double
implementasi tetap akan memberikan hasil yang identik di sebagian besar aplikasi.auto a = pi<float>;
benar-benar baik-baik saja, tentu lebih mudah dibaca kemudian terkenal4*atan(1)
Diedit - Untuk menghapus istilah yang diperlukan, karena terbukti kontroversial. Ini terlalu banyak istilah absolut.
C ++ adalah bahasa yang besar dan kompleks, untuk alasan itu Komite Standar hanya mencakup hal-hal yang sangat diperlukan . Sebisa mungkin diserahkan ke pustaka standar non-bahasa ... seperti Boost.
boost :: math :: constants
sumber
std::hermite
danstd::cyl_bessel_i
danstd::cosh
danstd::mersenne_twister_engine
danstd::ranlux48
danstd::cauchy_distribution
danstd::assoc_laguerre
danstd::beta
semua yang benar-benar diperlukan, kita semua menggunakan mereka setiap hari!