WinMain(HINSTANCE hInstance,




HINSTANCE hPrevInstance,

LPSTR lpszCmdLine,

Int nCmdShow)

{

MessageBox(NULL,"Привет","Без окна",MB_OK);

return 0;

}

 

В любом файловом менеджере или проводнике Window перейдите в папку и сделайте двойной щелчок мышью по этому файлу. Предполагается, что файлы с расширением .срр связаны с Builder ’ом. Builder загрузит файл и предложит создать проект для приложения, с чем следует согласиться. Далее, обычным образом клавишей F9 нужно запустить обработку проекта – компиляцию, линковку и запуск. В результате будет создан и выполнен исполняемый файл программы, и на экране вы увидите то, что показано ниже.

 

 

Что же мы здесь имеем? Обратимся к листингу. Прежде всего, отметим, что для всех приложений Windows, а именно с такими программами мы и работаем, практически всегда требуется подключение заголовочного файла windows.h. Далее, если мы не используем форму, то есть отходим от Builder -проекта по умолчанию, то необходимо использовать главную функцию WinMain. Это - аналог функции main в языке С. С нее начинается выполнение программы, а у нас она вообще единственная. В наши задачи сейчас не входит подробно знакомить читателя с синтаксисом тех или иных конструкций языка. Поэтому примите оформление функции WinMain в листинге в качестве «истины в последней инстанции», а если это вас не устраивает (и это прекрасно!), то читайте документацию. Укажем только, что функция имеет целый тип и, поэтому, последним выражением имеет оператор возврата return 0, хотя это возвращаемое значение нигде не используется.

Внутри функции WinMain мы вольны делать все, что нам захочется. А захотелось нам создать приветствие, но немного отличающееся от приветствия в первой программе. Для этой цели мы использовали функцию MessageBox. Если вы посмотрите в справку по этой функции, то увидите, что первым аргументом у нее должен быть указатель порождающего окна, а поскольку у нас такового нет, мы и поставили здесь NULL. Второй аргумент - текст, выводимый в окно сообщения. Здесь все ясно. Третий аргумент - текст в заголовке окна, что также не требует пояснений. Последний аргумент содержит системную константу, определяющую, что еще будет в окне. В данном случае в окне будет еще кнопка ОК, которая закрывает как само окно сообщения, так и всю программу.

Большинство приложений, создаваемых в Builder ’е могут иметь в своей основе окно, задаваемое формой так, что именно такая конфигурация нового создаваемого проекта предлагается по умолчанию. Огромное упрощение разработки программ достигается с помощью размещения на форме так называемых визуальных компонентов (VC), уже упомянутых и использованных в первой программе. Несомненно, и мы в дальнейшем будем использовать визуальные компоненты в нашей работе, в связи с чем необходимо поговорить об этих инструментах более подробно.

По сути дела VC являются объектами специализированных классов, инкапсулирующих в себе свойства (properties) и методы (methods). Кроме того, к членам классов визуальных компонентов следует отнести так называемые события (events) – «происшествия», случающиеся с VC. Главной особенностью этих специальных классов является то, что объекты VC обычно отображаются в окне формы в виде разнообразных визуальных конструкций: кнопок, полей ввода данных, полей выбора и многих других «картинок», которые мы видим при работе готовых программ в Windows. Как это не парадоксально звучит, но существуют и не визуальные VC. Эти объекты не отображаются в окнах работающих программ, а используются именно при разработке приложений. Вот со всеми этими премудростями нам сейчас и предстоит вкратце познакомиться. По-прежнему не будем излагать материал последовательно и скрупулезно, а проиллюстрируем все необходимое примерами.

Поставим себе следующую задачу. Необходимо разработать программу, которая при запуске открывает окно, представленное далее.

 

 

Здесь имеются две надписи, поле ввода числового значения и одна кнопка. В открывшемся окне мы должны иметь возможность изменить или оставить предложенным по умолчанию число. После нажатия кнопки ОК программа должна просто завершить свою работу, закрыть окно по истечению времени, указанного в поле ввода.

Создадим новый проект с формой, а это мы уже умеем делать, предварительно подготовив папку для проекта. Сохраните пока пустой проект. Поместите на форму визуальный компонент Label (метка) со вкладки Standard библиотеки VCL. Этот компонент обозначен большой буквой А. Как только вы положили VC на форму, он отобразится в окне инспектора объектов (Object Inspector) слева от формы. Здесь будет открыта вкладка свойств объекта Properties. В поле Caption сейчас написано Label1. Замените надпись на ЗАКРЫТЬ ПРОГРАММУ ЧЕРЕЗ. Текст в метке на форме соответственно изменится. Метку можно перемещать по форме, захватив ее мышью. Передвиньте компонент ближе к верхнему правому углу. Если после этого метка перестала отображаться в инспекторе (и там стала отображаться форма), просто снова щелкните по ней мышкой. Активизируйте свойство Color и по стрелке справа выберите цвет фона. Мы сделали его белым. Поместите правее метки компонент Edit с той же вкладки Standard. Свойство Text замените на 5000. Правее только что созданного поля редактирования поместите еще одну метку с текстом МИЛЛИСЕКУНД и тоже белым фоном. На этом этапе можно проверить, все ли у нас в порядке. Сохраните проект и запустите его на исполнение. У вас должно появиться окно с отображением созданных элементов. Закройте его.

Со вкладки System библиотеки визуальных компонентов возьмите таймер (Timer) и разместите его на форме. Таймер работает следующим образом. Как только он становится доступным, то есть, как только его свойство Enable становится ИСТИНОЙ (true), начинается отсчет времени. После того, как пройдет столько миллисекунд, сколько задано в свойстве таймера Interval, наступает событие OnTimer, реакцию на которое нужно запрограммировать. Таким образом, установите свойство таймера на вкладке Properties инспектора объектов в false (ЛОЖЬ) – сначала таймер должен быть заблокирован. Перейдите на вкладку событий и сделайте двойной щелчок мышью по пустому полю правее названия события OnTimer. Сразу же откроется главный текстовый модуль программы, где тут же сформируется функция-обработчик события. Тело функции пока пусто. Здесь мы должны написать выражение, задающее реакцию на событие. Реакция очень проста – закрыть программу. Для этого можно, например, вызвать функцию exit(1). Теперь обработчик события в текстовом модуле должен выглядеть следующим образом:

 

void __fastcall TForm1::Timer1Timer(TObject *Sender)

{

exit(1);

}

 

На следующем этапе разместим на форме кнопку, изменив название (свойство Name) с установленного по умолчанию Button1 на ОК - в поле Name напишите ОК и нажмите Enter. Теперь необходимо написать обработчик события OnClick щелчка по кнопке. Это, конечно, можно сделать через инспектор объектов, но, для основного события объекта, а для кнопки щелчок это основное событие, можно поступить проще. Просто сделайте двойной щелчок по кнопке на форме, и вы сразу попадете в текстовый модуль, в функцию-обработчик, которая тоже пока пуста.

Что необходимо написать в обработчике? Сначала нужно задать интервал срабатываний таймера. Этот интервал, выраженный в миллисекундах необходимо взять из поля редактирования и присвоить соответствующему параметру таймера. Напомним, что параметр Interval является свойством объекта Timer1, а текст в поле редактирования является свойством Text объекта Edit1. Казалось бы, что для достижения поставленной цели нужно применить выражение присваивания Timer1->Interval = Edit1->Text; Если мы вставим это выражение в обработчик и попробуем скомпилировать программу, то получим ошибку:

 

[C++ Error] Unit1.cpp(26): E2034 Cannot convert 'AnsiString' to 'unsigned int'.

 

Компилятор сообщает вам, что не может превратить выражение типа строка в выражение типа беззнаковое целое. Действительно, если вы обратитесь к справке по конструкции Interval для таймера и конструкции Text для поля редактирования, то увидите, что эти величины разного типа. Дело поправимое. Для конвертирования строки в целое существует специальная функция, и если в обработчике написать

 

Timer1->Interval = StrToInt(Edit1->Text);

 

то все будет в порядке.

Далее в обработчике щелчка по кнопке следует запустить таймер - присвоить свойству Enabled значение ИСТИНА (true). Окончательно функция-обработчик должна выглядеть следующим образом:

 

void __fastcall TForm1::OKClick(TObject *Sender)

{

Timer1->Interval = StrToInt(Edit1->Text);

Timer1->Enabled = true;

}

 

Теперь все готово к запуску программы. Сделаем это. Возможно, не лишним будет отметить, что после запуска приложения в поле редактирования значение 5000 миллисекунд, заданное нами по умолчанию, можно заменить на любое другое.

На этом изготовление программы заканчивается. Можно немного «навести красоту». Захватив мышкой рамку формы слева или справа, снизу или сверху, можно изменить размеры окна формы и привести их к виду, показанному на рисунке. Вместо безликого form1 можно задать имя окна формы через свойство Caption в инспекторе объектов. Наконец отметим, что таймер является тем самым не визуальным визуальным компонентом. При разработке он присутствует на форме, при исполнении программы он не виден.

 

Рисование графиков

 

Представление информации в виде графиков различных функциональных зависимостей, наверное, является наиболее наглядным. По этой причине целесообразно посвятить этому вопросу специальный раздел. Попутно здесь мы познакомимся с некоторыми не рассмотренными ранее инструментами разработки графического интерфейса.

Построение графиков проиллюстрируем конкретным примером. Сформулируем задачу следующим образом. На одном графике необходимо отобразить две функции – синус и косинус, при изменении аргумента функций в пределах от 0 до 10 радиан. Графики должны представлять собой ломаные линии, проходящие через узловые точки. Шаг следования узлов должен задаваться средствами графического интерфейса. Необходимо выполнить полную разметку осей (ординат и абсцисс). Для каждой функции должен использоваться свой стиль линий. Необходимо организовать подрисуночную подпись графика.

Прежде всего, создаем новый проект, оставив предлагаемый по умолчанию вариант приложения с формой. Проект сохраняем в рабочем каталоге. В верхней центральной части формы размещаем элемент МЕТКА (Label) из вкладки Standard линейки визуальных компонентов. Когда метка выделена мышью, слева от формы в окне инспектора объектов (Object Inspector) отображаются свойства этой метки. Перейдем там на поле Caption и заменим текст по умолчанию на STEP=. Эти надпись теперь и будет отображаться в метке. Теперь в инспекторе объектом перейдем на пункт Font и, активировав его мышью (щелчком немного правее), зададим размер символов, равный 14. Метка готова.

Немного правее только что сформированной метки разместим поле редактирования Edit с той же вкладки VCL. В поле Text инспектора объектов запишем вместо того, что было по умолчанию текст 50. Аналогично тому, как это было сделано для метки, выберем через пункт Font размер символов 14. Поле редактирования также готово.

Теперь на форме необходимо разместить область рисования графики. В качестве таковой можно использовать инструменты Image или PaintBox из линейки VCL. Остановим свой выбор на втором. Он находится на вкладке System линейки. Пользуясь мышью подберите размеры области так, чтобы она занимала почти всю ширину формы и оставляла место для двух кнопок в нижней части.

Ну и разместим эти две кнопки друг под другом или рядом друг с другом в самом низу формы. Измените имена кнопок в свойствах Caption в инспекторе объектов на START и FINISH. Теперь заготовка графического интерфейса программы готова. Выглядеть она должна примерно так, как это показано на следующем рисунке.

 

 

Все основные события в проектируемом приложении будут разворачиваться при нажатии на кнопку START на форме. В связи с этим необходимо перейти к редактированию кода программы в теле функции0бработчика соответствующего события. Делать это мы уже умеем. Итак, далее мы будем последовательно описывать выражение, которые нужно вписать в текс тела функции.

Для начала нам понадобятся две переменные целого типа. Переменная i, в основном, будет служить счетчиком циклов. Переменная step будет задавать шаг изменения горизонтальной координаты узла (аргумента функций синуса и косинуса). Производится обычное объявление локальных переменных.

 

int i,step;

 

Значение переменной step введем из поля редактировыния Edit. Делается это следующим образом.

 

step=StrToInt(Edit1->Text);

Конструкция Edit1->Text представляет собой строку символов, находящуюся в поле редактирования. В нашем случае изначально это строка “50”. Функция StrToInt, какэто следует из ее названия,производит преобразование строки в целое. Возвращаемое значение – целая константна, равная 50. Эта величина и присваивается переменной step. Если пользователь введет в поле редактирования другое значение, то оно станет актуальным для переменной step после очередного нажатия на кнопку START.

Область рисования PaintBox имеет инструмент Canvas – канва или холст для рисования. Именно этот инструмент располагает рядом свойств и методов, позволяющих выполнять все необходимые нам действия. Синтаксис обращений к методам и свойствам будут понятен из следующих фрагментов текста.

Сейчас нам необходимо установить стиль рисования линий. Исходно это должен быть стиль сплошной линии. Запишем следующее выражение:

 

PaintBox1->Canvas->Pen->Style=psSolid;

Здесь мы обращаемся к компоненту PaintBox, к его инструменту Canvas, к его свойству Pen (перо, карандаш) и к его свойству Style. Короче говоря, переменной Style присваивается значение psSolid, а это и есть стиль сплошной линии. Вообще говоря, стиль psSolid устанавливается по умолчанию, однако мы задаем его в явном виде, поскольку далее в программе мы стиль изменим, но исходные установки должны устанавливаться каждый раз при нажатии кнопки START.

Установим размер шрифта отображения символов на PaintBox равным 8. Заметим, что все размеры и единицы длины выражаются в пикселях - количествах точек.

 

PaintBox1->Canvas->Font->Size=8;

Особых комментариев здесь, видимо, не требуется.

Инструмент Brush (кисть) позволяет закрашивать замкнутые или выделенные области PaintBox заданным цветом, который устанавливается в свойстве Color. Зададим это цвет белым с использованием следующего выражения.

 

PaintBox1->Canvas->Brush->Color=clWhite;

Здесь, очевидно, тоже все понятно.

Теперь «зальем белой краской» все поле рисования.

 

PaintBox1->Canvas->FillRect(Rect(0,0,PaintBox1->Width,PaintBox1->Height));

 

Функция FillRect закрашивает прямоугольник.Прямоугольник, в своюочередь, определяется функцией Rect с четырьмя аргументами, определяющими левый верхний и правый нижний углы прямоугольника. Последние два значения определяются свойствами Width и Height компонента PaintBox. Здесь крайне важно знать, что система координат в поле рисования «перевернута». Начало координат (точка x=0, y=0) находится в левом верхнем углу, ось X направлена слева направо, а ось Y направлена сверху вниз/

Теперь нарисуем на холсте оси координат. Для проведения отрезков прямых линий мы можем воспользоваться двумя функциями: MoveTo и LineTo. Первая устанавливает перо (карандаш) в точку, координатами которой являются два аргумента функции X и Y. Координаты приводятся к типу целых чисел. Вторая функция рисует прямую, исходящую из текущей точки в точку, заданную аргументами функции. Прорисовка вертикальной м горизонтальной оси выполняется следующим четырьмя выражениями.

 

PaintBox1->Canvas->MoveTo(20,20);

PaintBox1->Canvas->LineTo(20,320);

PaintBox1->Canvas->MoveTo(20,170);

PaintBox1->Canvas->LineTo(1050,170);

Сначала перо устанавливается в точку с координатами 20,20, то есть с отступом в 20 пикселей вправо от левой границы холста и 20 пикселей вниз от верхней границы – помним о перевернутой системе координат! Далее проводится вертикально вниз прямая длиной 300 пикселей. Горизонтальная ось проводится на уровне 170 пикселей. Длина горизонтальной оси равна 1030 пикселей. Таким образом значение 0 для отображаемых далее функций синуса и косинуса будет соответствовать горизонтальному уровню 170 на холсте. Расставим небольшие вертикальные штрихи по оси Y, отмечающие значения некоторых опорных точек на этой оси. Иными словами, разметим вертикальную ось, поставив штрихи на расстоянии 100, 200, … 1000 пикселей от начала координат. Делается это с помощью цикла.

 

for(i=120; i<=1020; i+=100)

{

PaintBox1->Canvas->MoveTo(i,170);

PaintBox1->Canvas->LineTo(i,160);

}

 

Действия в цикле достаточно очевидны и комментариев не требуют.

Разметим вертикальную ось. Здесь достаточно изобразить два небольших горизонтальных штриха около оси Y на уровнях в 100 пикселей выше и 100 пикселей ниже начала координат. Для этого запишем в программе следующие 4 выражения.

 

PaintBox1->Canvas->MoveTo(20,70);

PaintBox1->Canvas->LineTo(30,70);

PaintBox1->Canvas->MoveTo(20,270);

PaintBox1->Canvas->LineTo(30,270);

 

Напротив только что прорисованных двух штрихов и немного левее вертикальной оси выставим числовые значения 1 и -1. Это будут отмасштабированные значения изображаемых тригонометрических функций. Для рисования этих значений воспользуемся функцией TextOutA отображения текста на холсте. Функция имеет три аргумента. Первые два – координаты левого верхнего угла области, в которой отобразится текст. Последним аргументом должна быть строка символов. Если в качестве выводимого текста фигурирует целое число, то оно само заменяет эту строку, но это скорее исключение, чем правило. Так, если бы была необходимость отобразить в виде текста вещественное число с десятичной точкой, то потребовалось бы преобразование числа в строку типа FloatToStr(6.75). Ну, а в нашем случае достаточно применить следующие выражения.

 

PaintBox1->Canvas->TextOutA(8,62,1);

PaintBox1->Canvas->TextOutA(4,262,-1);

Теперь проставим числовые значения около штрихов на горизонтальной оси.

 

for(i=120; i<=920; i+=200)

PaintBox1->Canvas->TextOutA(i-2,175,i/100);

Нетрудно понять, что под указанными штрихами отображаются цифры 1, 3, … 9. Это – отмасштабированные значения аргумента рисуемых тригонометрических функций. Внимательно посмотрите на последний фрагмент и разберитесь в том, что здесь абсолютно необходимо применить целочисленное деление i/100.

Приступаем к рисованию графика функции y=sin(x). Мы предполагаем, что аргумент функции будет меняться от 0 до 10. Сопоставим этому изменению аргумента изменение номера пикселя вдоль горизонтальной оси от 0 до 1000. Для этого меняем переменную i от 20 до 1020 с учетом того, что начало координат смещено на 20 пикселей от края канвы. В соответствие с этим аргумент функции должен вычисляться через i по формуле x=(i-20)/100.0. деление здесь должно быть именно вещественным, а не целочисленным.

Прежде всего, поскольку sin(0) равен нулю, необходимо установить перо в начало координат – в точку с координатами 20,170. Дальнейшее рисование производится в цикле с увеличением i на величину шага step.

 

PaintBox1->Canvas->MoveTo(20,170);

for(i=20+step; i<=1020; i+=step) PaintBox1->Canvas->LineTo(i,170-sin((i-20)/100.)*100);

Вертикальная координата очередной точки задается выражением 170-sin((i-20)/100.)*100. Во-первых, отсчитывать ее надо от оси Y, то есть от уровня 170. Во-вторых, значение синуса надо вычитать из 170, поскольку система координат перевернута. И, в-третьих, значение синуса умножается на 100 для масштабирования по вертикальной оси.

Прежде чем рисовать график второй функции – косинуса, изменим стиль линии со сплошного на штриховой. Установку стиля мы уже умеем делать, а название штрихового стиля будет psDash. Следовательно, далее в программе должна быть строка:

 

PaintBox1->Canvas->Pen->Style=psDash;

Функция cos(0), как известно, имеет значение 1. Тогда перед рисованием графика необходимо переместить перо в точку с координатами 20,70.

 

PaintBox1->Canvas->MoveTo(20,70);

 

И далее будет выполняться рисование в цикле.

 

for(i=20+step; i<=1020; i+=step) PaintBox1->Canvas->LineTo(i,170-cos((i-20)/100.)*100);

Последнее, что нужно отобразить на холсте, это некая подпись к рисунку. Пусть это будет строка ----------- - SIN, - - - - - - COS, но с увеличенным до 20 размером символов. Установим нужный размер.

 

PaintBox1->Canvas->Font->Size=20;

Снова используем инструмент вывода текста в нужное место холста.

 

PaintBox1->Canvas->TextOutA(400,280,"----------- - SIN, - - - - - - COS");

 

Вот и все, что необходимо написать в теле функции обработчика нажатия на первую кнопку START.

Кнопку FINISH мы организовали для закрытия программы (хотя это можно делать, разумеется, и стандартным закрытием окна программы. Полный выход из программы осуществляется в С++ функцией Close(). Ее-то и следует поместить в обработчик нажатия на вторую кнопку. Теперь программа полностью готова, и если в ней установить шаг прорисовки, равный 1, то есть самый минимально возможный, то на экране монитора можно будет видеть следующую картину.

 

 

 

ВВЕДЕНИЕ В ЧИСЛЕННЫЕ МЕТОДЫ

 

Обработка экспериментальных данных на компьютере

 

Обработка данных с использованием вычислительной техники является важнейшей отраслью современных информационных технологий. Для реализации задач обработки данных привлекаются разнообразные методы вычислительной математики. В данном разделе мы остановимся только на двух из таких методов – анализ корреляционных связей между двумя процессами и регрессионный анализ данных.

Прежде всего, необходимо отчетливо представлять, что любые экспериментальные данные, полученные в процессе измерений, содержат, наряду с некоторыми детерминированными функциональными связями, различного рода ошибки. Так, например, давление и температура при постоянном объеме связаны между собой прямой пропорциональной зависимость. Как это следует из универсального газового закона. Однако, во-первых, сам этот закон представляет собой некоторую идеализацию, и, во-вторых, экспериментальная проверка этого закона всегда будет содержать инструментальные ошибки так, что линейная зависимость будет наблюдаться лишь приближенно. Возникает вопрос: как количественно оценить эту самую степень приближенности. Ответ на этот вопрос как раз и дает корреляционный анализ. Итак, речь идет не об установлении строгой функциональной зависимости - в реальном эксперименте такая детерминированная зависимость скорее исключение, а не правило. Мы говорим о статистической связи – связи в среднем.

Для количественного описания статистической связи между двумя величинами вводят КОЭФФИЦИЕНТ ПАРНЫХ КОРРЕЛЯЦИЙ, который также известен как уоэффициент корреляции Пирсона. Если измерены два набора значений величин xi, yi, что наиболее наглядно можно представить как значения, измеренные в различные моменты времени t1, t2,... tN, то коэффициент корреляции между ними определяется по формуле:

Здесь угловые скобки < > означают усреднение, а sx, sy есть среднеквадратичные отклонения соответствующих величин.

Конкретно, в нашем случае, коэффициент корреляции рассчитывается следующим образом:

 

 

Эта формула построена так, что коэффициент корреляции может принимать значения в интервале [-1,+1]. При этом значения +1 и –1 достигаются только, если x и y связаны строго линейной зависимостью y=ax+b. Знак R, при этом, соответствует знаку коэффициента a. Таким образом, коэффициент парных корреляций является мерой близости статистической связи двух переменных величин к линейной зависимости. Если величина R близка по абсолютной величине к единице, то имеет место сильная корреляционная связь между величинами, а, если она мала по сравнению с 1, то измеренные величины можно считать независимыми.

Можно предложить несколько вариантов моделирования корреляционных связей между двумя процессами, наглядно иллюстрирующих методику применения коэффициента парных корреляций.

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

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

Вторая процедура, широко применяемая при обработке экспериментальных данных, позволяет наилучшим способом аппроксимировать взаимосвязь двух физических величин той или иной функциональной зависимостью. Речь идет о так называемом РЕГРЕССИОННОМ АНАЛИЗЕ данных. Считается, что предполагаемый характер связи двух величин x и y известен. Это может быть линейная, квадратичная зависимости, экспоненциальная связь или что-либо иное. Задачей регрессионного анализа является определение коэффициентов или параметров выбранной функциональной зависимости, при которых аппроксимирующая функция наиболее точно отображает наблюдаемые значения.

Допустим, предполагается, что величины x и y связаны между собой линейной зависимостью. В этом случае мы говорим о линейном регрессионном анализе. В плоскости XOY можно построить "облако" точек с координатами xi, yi, i=1,2,...N, полученных в результате измерений, как это показано на рисунке.

 

 

Нашей задачей является выбор коэффициентов a и b функциональной зависимости y=ax+b, при которых соответствующая прямая проходит через "облако" точек наилучшим образом. Для того чтобы конкретизировать это самое понятие "наилучшим образом" прибегнем к МЕТОДУ НАИМЕНЬШИХ КВАДРАТОВ. В общем случае аппроксимирующую зависимость y=f(x;a,b,c,...) будем рассматривать как функцию от параметров a,b,c,... Величину yi-f(xi;a,b,c,...) называют невязкой для i - й экспериментальной точки. Она показывает, насколько данная точка не укладывается в выбранную аппроксимирующую зависимость. Очевидно, что невязка может быть как положительной, так и отрицательной. В частности, на предыдущем рисунке невязка для выбранной точки показана вертикальным отрезком, соединяющим точку с аппроксимирующей прямой, и здесь она положительна.

В основу метода наименьших квадратов положено требование минимальности суммы квадратов невязок:

Фигурируют именно квадраты, поскольку невязки могут иметь разные знаки. Величину J можно рассматривать как функцию параметров a,b,c,.... Тогда условие минимальности функционала невязок будет представлять собой систему уравнений:

Для линейной регрессии будем иметь:

Имеем систему двух линейных алгебраических уравнений с двумя неизвестными, решение которой дает расчетные формулы линейного регрессионного анализа:

При использовании более сложной, по сравнению с линейной, регрессии, задача определения параметров несколько усложняется, но принципиальных трудностей и здесь не возникает.

 

Решение трансцендентных уравнений

 

В данном разделе речь идет о численных методах решения уравнения f(x)=0 в области действительных чисел. В общем случае функция f(x) может быть совершенно произвольной, в отличие, например, от линейной или степенной, то есть алгебраической. В математике в этом общем случае говорят о так называемых трансцендентных уравнениях. В общем виде задача может быть сформулирована следующим образом. Необходимо найти такое значение x1, которое приближенно совпадает со значением x0, обращающим уравнение в тождество. Требуется, однако, существенно дополнить постановку задачи. Во-первых, поскольку уравнение может и не иметь решения, следует быть уверенным в том, что поставленная задача имеет смысл - нельзя поймать черную кошку в темной комнате, если ее там нет. Во-вторых, поскольку уравнение может иметь несколько корней, необходимо ограничить интервал поиска корня отрезком [a,b], для которого известно, что на нем имеется только один корень. Признаком этого является то, что f(a) и f(b) имеют разные знаки. Термин "приближенно совпадает" также требует пояснения. Все приближенные методы нахождения корня строятся на основе итераций, когда очередное значение так или иначе получается из предыдущего и все ближе подходит к точному значению корня. Теперь можно сформулировать условие прекращения этого итерационного процесса. Процесс поиска корня следует прекратить тогда, когда относительная разность двух последовательных приближений станет по абсолютной величине меньше заданной точности. Если максимальная допустимая ошибка задана величиной e, а два последовательных приближения являются значениями xn-1 и xn, то условие прекращения итераций примет вид:

.

Неприятность может произойти, если корнем уравнения является 0, однако это уже совсем особый случай, который рассматриваться не будет.

Наиболее наглядным, простым в реализации, однако, увы, не самым лучшим численным методом поиска корней, является МЕТОД ДЕЛЕНИЯ ОТРЕЗКА ПОПОЛАМ. Суть метода проще всего проиллюстрировать графически, с помощью следующего рисунка.

 

 

 

 

Прежде всего, находится точка , делящая отрезок [a,b], на котором ищется корень, пополам. Еще раз напомним, что корень на этом отрезке обязан быть. Далее, из этих двух половин выбирается та, на концах которой функция имеет разные знаки, то есть та, на которой имеется корень. Если эта половина является отрезком [c,b], как на нашем рисунке, то новым левым концом отрезка становится точка с. В противном случае точка с становится новым правым концом отрезка. Таким образом, после каждого такого выбора мы имеем новый отрезок [a,b], к которому снова применяем половинное деление. В этом методе наиболее наглядно выглядит условие выхода из цикла . А почему мы здесь обошлись без знака абсолютного значения? Автор надеется, что читатель сможет дать ответ на этот вопрос самостоятельно.

Более быстродействующим, по сравнению с методом половинного деления, является способ поиска корня, названный МЕТОДОМ ХОРД. Графическая иллюстрация метода представлена на рисунке, приведенном ниже. Для построения алгоритма метода хорд необходима дополнительная информация о характере поведения функции на интервале поиска корня. Прежде всего, необходимо гарантировать, что на этом интервале функция монотонна (монотонно возрастает или монотонно убывает). Кроме того, на всем интервале не должен меняться характер выпуклости или вогнутости. Иными словами, на [a,b] не должны менять знак ни первая, ни вторая производные функции. Вообще говоря, даже и при нарушении этих условий метод хорд можно применять, но с использованием специальных приемов, на которых мы не будем останавливаться. Проще всего в сомнительных случаях просто сузить интервал до такого размера, на котором производные знак не меняют.

 

 

 

Из геометрии рисунка (подобия треугольников) можно найти точку m пересечения хорды с осью абсцисс. Поскольку , то . Дальнейшее построение алгоритма зависит от соотношения знаков первой и второй производных. Если знаки производных различны - левая часть рисунка, то новым правым концом интервала поиска корня становится точка m, то есть делается замена b на m. В противном случае, соответствующем двум вариантам правой части рисунка, делается замена a на m. Итерационный процесс продолжается до достижения необходимой точности.

Метод хорд действительно значительно более оперативен по отношению к методу деления отрезка пополам. В этом можно убедиться, реализовав оба метода для нахождения корня одного и того же уравнения на одном и том же отрезке и при одной и той же точности. Следует, однако, заметить, что выигрыш во времени будет иметь место только при оптимально написанной программе. В первую очередь, необходимо сократить до минимума количество вызовов функции f(x). Так в приведенном выше выражении для величины m по два раза фигурируют функции f(a) и f(b). Разумеется, функцию необходимо посчитать один раз, запомнить ее значение в какой-либо переменной и во второй раз использовать уже не вызов функции, а эту переменную.

Рассмотренные методы не исчерпывают арсенала средств поиска корней уравнений. Существуют методы более оптимальные либо по времени, либо по расходованию памяти компьютера. Кроме того, имеются методики, оптимальные для конкретных видов функций, для которых решается уравнение. Так, например, существуют алгоритмы, позволяющие находить группы корней, если функция является алгебраическим полиномом (причем корни могут быть найдены в комплексной области). Алгоритмы эти выглядят, однако, довольно сложными и не могут быть рассмотрены здесь.

 

Вычисление определенных интегралов

 

Необходимость в вычислении определенных интегралов с использованием численных методов возникает, в основном, в двух случаях. Во-первых, подынтегральная функция может быть задана таблично, например, как полученная в результате каких-либо измерений. Во-вторых, первообразная не может быть найдена в аналитическом виде, то есть, интеграл не является табличным. Как и все вычислительные методы, численное интегри



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: