Существует довольно глупая проблема с числом пи в C и C ++. Насколько я знаю, M_PI
определено в math.h
не требуется ни одного стандарта.
Новые стандарты C ++ ввел много сложных математических в стандартной библиотеке - гиперболических функций, std::hermite
и std::cyl_bessel_i
, различных генераторов случайных чисел и так далее , и так далее.
Приносил ли какой-нибудь «новый» стандарт константу для пи? Если нет - почему? Как все это сложная математика работает без нее?
Мне известны подобные вопросы о пи в С ++ (им уже несколько лет и они соответствуют стандартам); Я хотел бы знать текущее состояние проблемы.
Меня также очень интересует, почему C ++ до сих пор не имеет константы pi, но имеет много более сложной математики.
UPD: я знаю, что могу сам определить pi как 4 * atan (1) или acos (1) или double pi = 3.14. Конечно. Но почему в 2018 году я все еще должен это сделать? Как стандартные математические функции работают без пи?
UPD2: Согласно этому отчету о поездке на заседание Комитета C ++ в июле 2019 года в Кельне, предложение P0631 (математические константы) было принято в C ++ 20. Похоже, наконец-то у нас в стандартной библиотеке будет число pi!
Ответы:
До C ++ 17 включительно pi это не константа, введенная в язык, и это боль в шее.
Мне повезло, что я использую повышение, и они определяют pi с достаточно большим количеством десятичных разрядов даже для 128 бит
long double
.Если вы не используете Boost, то сделайте это самостоятельно. Определение его с помощью тригонометрической функции заманчиво, но если вы сделаете это, вы не сможете сделать это a
constexpr
. Точность тригонометрических функций также не гарантируется ни одним из известных мне стандартов ( ср .std::sqrt
), Так что на самом деле вы находитесь в опасной ситуации, действительно полагаясь на такую функцию.Есть способ получить
constexpr
значение для пи с помощью метапрограммирования: см. Http://timmurphy.org/2013/06/27/template-metaprogramming-in-c/С C ++ 20 хорошие новости. Там является defininition для пи . C ++ 20 добавляет некоторые математические константы в
<numbers>
. Напримерstd::numbers::pi
, этоdouble
тип.Ссылка: https://en.cppreference.com/w/cpp/numeric/constants
источник
constexpr
сожалению, это не может быть , поэтому я говорю: «Определение его с помощью функции триггера - это боль»double
(или некоторого смешного числа, если вам небезразличны гипотетические действительно длинные двойные числа).fsin
инструкцией «около 1,37 квинтиллионных единиц в последнем месте, оставляя правильными менее четырех бит» , и это еще хуже для больших входов, где уменьшение диапазона повторяется несколько раз. Это несколько касательно констант, используемыхlong double
в C ++, но в любом случае аккуратно.Как говорили другие, нет
std::pi
но если вы хотите получить точноеPI
значение, вы можете использовать:Это предполагает, что ваша реализация C ++ производит правильно округленное значение PI from
acos(-1.0)
, что является обычным, но не гарантированным .Это не так
constexpr
, но на практике оптимизирующие компиляторы, такие как gcc и clang, оценивают его во время компиляции. Однакоconst
для оптимизатора важно сделать хорошую работу.источник
acos()
функция имеет бесконечный наклон вx = -1
. Следовательно, этот метод опирается наacos()
реализацию, которая в основном явно определяет случай точного-1
аргумента и возвращает правильную константу напрямую. Лучше использовать что-то вроде4*atan(1)
математически гораздо более надежного (уклон при хорошем поведенииx = 1
и умножение на 4 всегда точнее с математикой с плавающей точкой).std::acos
в постоянном выражении. Clang сообщает об этом как об ошибке. Пожалуйста, обратите внимание, что это несоответствующее расширение, которое должно быть исправлено в gcc. Пожалуйста, обратитесь к этому ответу для более подробной информации.До C ++ 20 нет, ни один из стандартов не вводит константу, которая представляла бы число pi (π). Вы можете приблизить число в вашем коде:
Другие языки, такие как C # есть константу, объявленную в их библиотеках.
Обновление: Начиная с C ++ 20,
pi
внутри<numbers>
заголовка действительно объявлена константа . Доступ к нему осуществляется через:std::numbers::pi
.источник
inline
для C ++ 17 +.double
. В C # это легко, посколькуdouble
тип исправлен. Если бы я был в комитете по стандартам C ++, я бы предложил что-то вродеstd::constants<double>::pi
std::numeric_limits<double>::is_iec559;
в этом случае вы должны утверждать статичность . Который, я признаюсь, является тем, что я имею в своем "главном заголовке". Обратите внимание, что формально вам нужно проверять все типы с плавающей запятой отдельно. То, что один из них - IEEE754, не означает, что они все.M_PI
определяется стандартом, если не языковым стандартом: POSIX с расширением X / Open System Interfaces (которое очень часто поддерживается и требуется для официального брендинга UNIX).Пока еще не ясно, что будет в C ++ 20, но поскольку вы спросили: у него, вероятно, будут такие константы . Документ был объединен в последнем раунде функций C ++ 20 (для проекта комитета в августе 2019 года).
В частности, будет
std::numbers::pi
(типаdouble
) и шаблон переменной, который вы можете использовать, если вы хотите другой тип с плавающей запятой, напримерstd::numbers::pi_v<float>
. Полный список констант можно увидеть в [numbers.syn] .источник
Это, очевидно, не очень хорошая идея, потому что нет очевидного типа, с помощью которого можно определить пи, который универсально применим во всех областях.
Pi, конечно, иррациональное число, поэтому оно не может быть правильно представлено ни одним типом C ++. Поэтому вы можете утверждать, что естественный подход состоит в том, чтобы определить его в наибольшем доступном типе с плавающей запятой. Тем не менее, размер самого большого стандартного типа с плавающей запятой
long double
не определяется стандартом C ++, поэтому значение константы в разных системах будет различным. Хуже того, для любой программы, в которой рабочий тип не был такого большого типа, определение числа «пи» было бы неуместным, так как оно накладывало бы затраты на производительность при каждом использовании числа «пи».Любой программист также тривиально находит значение pi и определяет свою собственную константу, подходящую для использования, поэтому он не дает большого преимущества для включения ее в математические заголовки.
источник
pi
полиморфной константы - это четкий путь вперед - на языке с выводом типа Хиндли-Милнера. В Haskell у нас всегда былоpi :: Floating a => a
так, чтобыpi
это автоматически имело значение3.1415927
вFloat
контексте,3.141592653589793
вDouble
контексте иπ
в контексте символьных вычислений. Но люди действительно хотели бы иметь необходимость явно создавать экземпляр параметра шаблона? Кажется немного неловким, особенно если фиксированнаяlong double
реализация даст идентичные результаты в большинстве приложений.auto a = pi<float>;
вполне нормально, безусловно, более читабельное, чем печально известное4*atan(1)
Отредактировано - удалить термин необходимо, потому что это оказалось спорным. Это слишком много абсолютного термина.
C ++ - это большой и сложный язык, поэтому Комитет по стандартам включает в себя только то, что настоятельно необходимо . Как можно больше оставлено для неязыковых стандартных библиотек ... типа Boost.
повышение :: Math :: константы
источник
std::hermite
иstd::cyl_bessel_i
иstd::cosh
иstd::mersenne_twister_engine
иstd::ranlux48
иstd::cauchy_distribution
иstd::assoc_laguerre
иstd::beta
все были абсолютно необходимы, все мы используем их каждый день!