Кто-нибудь может объяснить, почему scipy.integrate.quad дает разные результаты для одинаково больших диапазонов при интегрировании sin(X)?

StackOverflow https://stackoverflow.com/questions/581186

Вопрос

Я пытаюсь численно интегрировать произвольную (известную при написании кода) функцию в свою программу используя методы численного интегрирования.Я использую Python 2.5.2 вместе с пакетом численного интегрирования SciPy.Чтобы получить представление об этом, я решил попробовать интегрировать sin(x) и наблюдал за этим поведением-

>>> from math import pi
>>> from scipy.integrate import quad
>>> from math import sin
>>> def integrand(x):
...     return sin(x)
... 
>>> quad(integrand, -pi, pi)
(0.0, 4.3998892617846002e-14)
>>> quad(integrand, 0, 2*pi)
(2.2579473462709165e-16, 4.3998892617846002e-14)

Я нахожу такое поведение странным, потому что -
1.При обычном интегрировании интегрирование по полному циклу дает ноль.
2.При численном интегрировании, это (1) не обязательно так, потому что вы можете просто быть аппроксимации общей площади под кривой.

В любом случае, либо предполагая, что 1 истинно, либо предполагая, что 2 истинно, я нахожу такое поведение непоследовательным.Либо оба интегрирования (от-pi до pi и от 0 до 2*pi) должны возвращать 0.0 (первое значение в кортеже является результатом, а второе - ошибкой), либо возвращают 2.257...

Может кто-нибудь, пожалуйста, объяснить, почему это происходит?Действительно ли это несоответствие?Может кто-нибудь также сказать мне, не упускаю ли я чего-то действительно базового в численных методах?

В любом случае, в моем окончательном приложении я планирую использовать описанный выше метод для определения длины дуги функции.Если у кого-то есть опыт в этой области, пожалуйста, посоветуйте мне наилучшую политику для выполнения этого на Python.

Редактировать
Примечание
У меня уже есть первые дифференциальные значения во всех точках диапазона, хранящиеся в массиве.
Текущая ошибка допустима.
Конечная нота

Я читал об этом в Википедии.Как указал Дмитрий, я буду интегрировать sqrt(1 + diff(f (x), x) ^ 2), чтобы получить длину дуги.То, что я хотел спросить, было - есть ли лучшее приближение / Лучшая практика (?) / более быстрый способ сделать это.Если потребуется больше контекста, я опубликую его отдельно / разместите контекст здесь, как вы пожелаете.

Это было полезно?

Решение

В quad функция - это функция из старой библиотеки Fortran.Он работает, оценивая по плоскостности и наклону интегрируемой функции, как учитывать размер шага, который он использует для численного интегрирования, чтобы максимизировать эффективность.Это означает, что вы можете получить немного разные ответы от одного региона к другому, даже если они аналитически одинаковы.

Без сомнения, оба интегрирования должны возвращать ноль.Возврат чего-то, что составляет 1 / (10 триллионов), довольно близок к нулю!Небольшие различия связаны со способом quad переворачивается sin и изменяя размеры его шага.Для вашей запланированной задачи, quad это будет все, что вам нужно.

Редактировать:За то, что ты делаешь, я думаю quad это прекрасно.Это быстро и довольно точно.Мое последнее утверждение - используйте его с уверенностью, если только вы не обнаружите чего-то, что действительно пошло наперекосяк.Если он не возвращает бессмысленный ответ, то, вероятно, он работает просто отлично.Не беспокойся.

Другие советы

Я думаю, что это, вероятно, машинная точность, поскольку оба ответа фактически равны нулю.

Если вы хотите получить ответ из первых уст, я бы разместил этот вопрос на дискуссионная доска scipy

Я бы сказал, что число O (10 ^ -14) фактически равно нулю.Какова ваша терпимость?

Возможно, алгоритм, лежащий в основе quad, не самый лучший.Вы могли бы попробовать другой метод интеграции и посмотреть, улучшит ли это ситуацию.Рунге-Кутта 5-го порядка может быть очень хорошей техникой общего назначения.

Это может быть просто природа чисел с плавающей запятой: "Что должен знать каждый специалист по информатике об арифметике с плавающей запятой".

Этот вывод кажется мне правильным, поскольку здесь у вас есть оценка абсолютной ошибки.Интегральное значение sin (x) действительно должно иметь нулевое значение для полного периода (любого интервала длиной 2 * pi) как при обычном, так и при числовом интегрировании, и ваши результаты близки к этому значению.
Чтобы оценить длину дуги, вы должны вычислить интеграл для функции sqrt(1 + diff(f (x), x) ^ 2), где diff (f (x), x) является производной от f (x).Смотрите также Длина дуги

0.0 == 2.3e-16 (absolute error tolerance 4.4e-14)

Оба ответа одинаковы и правильный т.е. ноль в пределах заданного допуска.

Разница проистекает из того факта, что sin(x)=-sin(-x) точно даже с конечной точностью.Принимая во внимание, что конечная точность дает sin (x) ~ sin (x + 2 * pi) только приблизительно.Конечно, было бы неплохо, если бы quad был достаточно умен, чтобы разобраться в этом, но на самом деле у него нет способа узнать априори, что интеграл по двум заданным вами интервалам эквивалентен или что первый результат лучше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top