Что нового

[Математика] вычисление интегралов

Arei

Скриптер
Сообщения
938
Репутация
115
Скажите пожалуйста есть ли код для вычисления интеграла в автоите.Заранее спасибо.


Добавлено:
Сообщение автоматически объединено:

Я про библиотеку какую нибудь.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Arei
берешь любой приближенный алгоритм нахождения интеграла и вычисляешь :smile:
готовой функции нет.
 
Автор
A

Arei

Скриптер
Сообщения
938
Репутация
115
вот именно что я не знаю да же приближенно как можно сделать.Можете помочь примером пожалуйста.заранее спасибо.Уважаемые форумчане
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Выбирай любой - Численное интегрирование
OffTopic:
А вообще странно, зачем тебе понадобилось считать интегралы, если ты не в курсе как считать его приближенно :-\
 
Автор
A

Arei

Скриптер
Сообщения
938
Репутация
115
Спасибо,но тема не закрыта если кто то сможет, то жду примера.Заранее спасибо.
 

shm_alex

Новичок
Сообщения
34
Репутация
4
Arei сказал(а):
Спасибо,но тема не закрыта если кто то сможет, то жду примера.Заранее спасибо.
Мне задача не понятна Какие входные данные , какие выходные. Что такое вычисление интеграла? Численное решение? или нужна формула ?
надо сказать что число пи наример, непредставимо действительным числом, а тем более числом float , double и т.д.
При при численном интегрировании неизбежны ошибки не только в предсатвлении функции , расчёте интеграла, формировании ответа и так далее.
Более того увидев в ответе число 4,9348022005446793094172454999381 вы с трудом поймёте что это приблежение числа PI^2/2 максимально представимое в дабл арифметике.Можно наверно прикрутить к AutoIt например бесплатную Maxima http://maxima.sourceforge.net/ru/ (Система символьных вычислений) ей передавать данные и их выводить .
В общем задача непонятна. А чтобы что то и как то считать в AutoIt есть все средства.
Грамотно поставленная задача 90% от её решения.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Вот одна из реализаций метода прямоугольников
Код:
$a = 0; Левая граница интервала
$b = 1; Правая
$y = 'Sin(x)'; Функция (только "x" - в качестве аргумента)

Func yVal($y, $x)
	Return Execute(StringReplace($y, "x", $x))
EndFunc

Func integral($y, $a = 0, $b = 1, $e = 1e-6); $y - функция, $a, $b - границы, $e - точность вычислений
	$N = 2; Начальное кол-во интервалов
	$iInt_old = 1/0; Начальное значение инеграла (бесконечность)
	Do
		$h = ($b - $a)/$N; Шаг интегрирования
		$iSum = 0
		For $i = 1 to $N
			$x = $a + $i*$h - $h/2;
			$iSum += yVal($y, $x)*$h
		Next
		$iDiff = Abs($iSum - $iInt_old); Разница вычислений на каждом шаге по сравнению с предыдущим
		$iInt_old = $iSum
		$N += 1
	Until $iDiff < $e; Конец вычислений, если разница стала меньше точности вычислений
	Local $retvals[3] = [Round($iInt_old, 5), $N - 2, Round($iDiff, 5)]; Возвращаемый массив из [значения интеграла, кол-ва итераций, локальной ошибки]
	Return $retvals
EndFunc

$val = integral($y, -1, 1)
MsgBox(64, "Определенный интеграл", "Значение интеграла от функции y(x) = " & $y & " равно " & $val[0] & @CRLF & _
"Количество итераций для вычислений - " & $val[1] & @CRLF & _
"Ошибка составила - " & $val[2])
 

shm_alex

Новичок
Сообщения
34
Репутация
4
Код:
$a = 0; Левая граница интервала
$b = 1; Правая
$y = '1/sqrt(x)'; Функция (только "x" - в качестве аргумента)

Func yVal($y, $x)
    Return Execute(StringReplace($y, "x", $x))
EndFunc

Func integral($y, $a = 0, $b = 1, $e = 1e-6); $y - функция, $a, $b - границы, $e - точность вычислений
    $N = 2; Начальное кол-во интервалов
    $iInt_old = yVal($y, ($b-$a)/2)*($b-$a); Начальное значение интеграла 
    Do
        $h = ($b - $a)/$N; Шаг интегрирования
        $iSum = 0
		$x=$a+$h/2;добавил начальное значение х в которой считать первую среднюю линию трапеции
        For $i = 1 to $N
            ;$x = $a + $i*$h - $h/2;
			$x+=$h;Заменил чтобы в цикле не умножать много раз $i*$h
            ;$iSum += yVal($y, $x)*$h
			$iSum += yVal($y, $x);сначало посчитаем сумму вскобках чтобы 100 раз не умножать в цикле и не накапливать ошибку вынесем высоту трапеции h за скобки
        Next
		$iSum*=$h ; зделаем умножение за скобками 
        $iDiff = Abs($iSum - $iInt_old); Разница вычислений на каждом шаге по сравнению с предыдущим
        $iInt_old = $iSum
        $N += 1
    Until $iDiff < $e; Конец вычислений, если разница стала меньше точности вычислений
    Local $retvals[3] = [Round($iInt_old, 5), $N - 2, Round($iDiff, 5)]; Возвращаемый массив из [значения интеграла, кол-ва итераций, локальной ошибки]
    Return $retvals
EndFunc

$val = integral($y,0,4)
MsgBox(64, "Определенный интеграл", "Значение интеграла от функции y(x) = " & $y & " равно " & $val[0] & @CRLF & _
"Количество итераций для вычислений - " & $val[1] & @CRLF & _
"Ошибка составила - " & $val[2])

немного я бы изменил код,
по-поводу алгоритма
он действительно что-то считает
но вот прикольную функцию предлагаю проинтегрировать этим методом
1/(sqrt(x)) от 0 до 1 легко видеть что аналитически вычисленый интеграл равен 2 а вот алгоритм походу расходится.. (впадает в бесконечный цикл- тк f(0)- стремится к бесконечности а вот первооразная в нуле - конечное число ))) )
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
shm_alex
1. твой код считает неверно
2. код приведенный мной считает верно, но в силу малой скорости сходимости, порог чувствительности нужно увеличить
3. в моем коде не используется значение функции в самой сингулярной точке (в нуле)


Добавлено:
Сообщение автоматически объединено:

забыл сказать, замечания по оптимизации приняты. писал на скорую руку.
 

shm_alex

Новичок
Сообщения
34
Репутация
4
Kaster сказал(а):
shm_alex
1. твой код считает неверно
Код не мой , а твой, я даже не примазываюсь. ) Мне он понравился .
Вот код отсчитал >
"C:\Program Files\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "C:\Program Files\AutoIt3\Examples\Shm\Debug\Integr.au3"
>Exit code: 0 Time: 3441.260
я просто думал он завис и расходится
теперь что неправильно и какой код правильней
да для флоат арифметики дистрибутивный закон умножения относительно сложения не действует :
f(x_1)*h+f(x_2)*h+f(x_3)*h+...+f(x_n)*h <>h*(f(x_1)+....f(x_n))
так какая же из сумм будет ближе к искомому интегралу
надо думать , но мне кажется зависит от функции
....

Зы, на принтскрине имнтеграл (1/sqrt(x)) от нуля до 2 поэтому он отсчитал верно почти ... если б сумму выше считать начиная с маленьких членов см график ещё выше то результат былбы точнее . ..
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
shm_alex
я ошибся. твой код считает норм. просто я проглядел что у тебя пределы другие.


Добавлено:
Сообщение автоматически объединено:

shm_alex [?]
так какая же из сумм будет ближе к искомому интегралу
теория говорит, что вычисления с использованием средних прямоугольников точнее чем крайних при одном и том же кол-во итераций ;) и дело не в машинном отличии свойства дистрибутивности, а в выборе узлов интегрирования. я выбираю середину между двумя соседними, а ты правый
 

shm_alex

Новичок
Сообщения
34
Репутация
4
Не согласен , если я тебя правильно понял имеется ввиду следующее
Что площадь S_1 Точнее предсталяет площадь фигуры чем площадь S2 и S0 - я не согласен. существуют функции для которых это не так. Кстати, если приглядется прямоугольники выбраны такие как и у тебя просто умножение заменено суммой в цикле for.
Я говорил о другой ошибке , просто при сложении чисел ( http://www.softelectro.ru/ieee754.html ) с плавающей точкой в машине происходит с начало выравнивание мантис сложение и потеря младших битов. В машинной арифметике с плавающей точкой как ни крути мантиса имеет конечное число битов для
и тут ходит на первый план порядок суммирования ведь для машины
10000000000000000000000000000000+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1=10000000000000000000000000000000
а
0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+10000000000000000000000000000000=
10000000000000000000000000000001
поэтому сначала надо просуммировать маленькие числа а потом большие , для выбранной функции 1/sqrt(x) - имеет решающее значение , в близи нуля функция быстро растет и мы начинаем складывать сначала большие значения функции потом маленькие что и вносит основную ошибку
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
shm_alex [?]
твое право. можешь почитать тут - Численное интегрирование: Метод прямоугольников начиная с третего абзаца, там где "очевидно".
существуют функции для которых это не так
однакож привел ты пример функции, для которой это так ;)
я понимаю, про ошибку о которой ты толкуешь, но подобного рода ошибки у меня ничтожно малы. а у тебя? ;) проверяется ведь легко, достаточно выводить на консоль каждую итерацию. операций со сверхбольшими и сверхмалыми числами у меня не возникало. потому что каждое большое число возникающее при при малых значениях из интервала умножается на маленькое число - длина интервала что делает это произведение пригодным для работы. у тебя же, складываются большие числа на одном конце интервала с малыми числами на другом, где собственно и копится ошибка.
прямоугольники выбраны такие как и у тебя
опять мой прокол. просто я не люблю копаться в чужом коде ;D
 
Верх