Здравствуйте.
Нужно написать програмку по вычислению некоторых формул.
Исходники и пример приводятся в маткаде.
Вроде бы проблем с большинством формул нету но попалась функция Find и я даже не могу толком сформулировать запрос чтобы решить вот такую хрень:
По отдельности все интегралы беруться отлично. Но в данном случае как я понял из мануалов маткада функция Find находит корень решения Lx1 при котором уравнение равно нулю.
Все бы ничего но я понятия не имею как вывести неизвестную из под интеграла… нас такому даже в универе не учили. Где взять исходник этой функции??
Может кто нибудь помочь??
Это из теории вероятности и метрологии. Честно уже плохо помню что там к чему.
Возьмем штангенциркуль и нарисуем круг и начнём измерять его линейкой(на телефоне поставить программу рулетка). Фактический размер 6 мм. Но каждый раз у нас есть ошибки измерения 6,0 то 5,9 то 5,8. Математическое ожидание каждый раз изменяется от числа измерений. Ясно что размер круга постоянный, а ошибки связаны с методом измерения. Ошибки не могут иметь произвольные значения и имеют интервал допустимости. А так же распределение ошибок имеют некоторый вид erf(x) . Error function сокращенно erf.
Если плотность вероятности случайной величины задана функцией Гаусса, а мы хотим найти вероятность события, то мы интегрируем плотность и получаем функцию ошибок(error function).
Исторически сложилось, что функция erf связана именно с Гаусса, а не с любой другой функцией.
Вот так вот выглядит определеннее функции ошибок:
Ньютона делать не стал сделала простым перебором. Поэтому считает около 10 секунд.
function erf(x:Real):Real;
var t,dt,h1,h2,s:Real;
i:Integer;
begin
dt:=0.0001;
s:=0;
h1:=0;
for i:=0 to Round(x/dt)-1 do
begin
t:=i*dt;
h2:=exp(-t*t);
S:=S+(h1+h2)/2*dt;
h1:=h2;
end;
result:=2/sqrt(Pi)*s;
end;
procedure TForm1.Button1Click(Sender: TObject);
var Lx1,Lx,sigma_ix,delta_x,y:Real;
i:Integer;
y0,Lx0:Real;
begin
Lx:= 0.25;
sigma_ix:=0.125;
delta_x:= 0.048;
for i:=1 to 10000 do
begin
Lx1:=i/1000;
y:=1/Lx1*erf(Lx1/2/sqrt(2))-1/Lx*erf(1/sqrt(2)*Lx/(2*sqrt(1+(sigma_ix+delta_x)*(sigma_ix+delta_x))));
Chart1.Series[0].AddXY(Lx1,y);
if i=1 then
begin
y0:=y;
Lx0:=Lx1;
end;
if abs(y-0)<abs(y0-0) then
begin
y0:=y;
Lx0:=Lx1;
end;
end;
Memo1.Lines.Add('Результат find');
Memo1.Lines.Add(Format('y0=%.03f; Lx1=%.03f;',[y0,Lx0]));
end;
Тут ошибка, у меня там в 10 раз больше шаг. Я границы для Lx1 проставлял жестко от 0 до 10 с шагом 0,001. Что-бы график построить и посмотреть что там два корня. В маткаде условии начинают с 0.25 что-бы отсечь первый корень и взять второй. Соответственно в Вашем коде это надо в параметры функции выносить.
Lx1 = (float)i / (float)MxSteps*10;
Мы не можем искать корень с той же точностью, что и считаем интеграл. Поэтому интеграл я считаю на 10 точнее. И плюс я считаю на double вы на float. Думаю дело в типах и там теряется точность.
Если интеграл заменить рядом Тейлора будет по быстрее и поточнее.
Я до конца так и не понял всех преобразований до функции erf(x), но может быть где то закралась ошибка?? Врядли эти погрешности высплывают из за типов чисел.
Уже перепроверил и в математике и в коде … даже не знаю что поправить.
А как выяснилось это ключевой момент всех вычислений. Если тут дать ошибку то дальше все плывет …