Лекция 2 Типове данни. Класове и обекти. Числено интегриране



Дата25.07.2016
Размер103.65 Kb.
#4961
ТипЛекция




Лекция 2 Типове данни. Класове и обекти. Числено интегриране.
Когато обявим променлива, трябва да укажем от какъв тип е. Типът е или вграден (например int, char, double, float) или клас, наричан още абстрактен тип (например Scanner, System, Graph). В таблицата са показани основните вградени типове и техните размери.

Име

вид

битове

байтове

boolean

Логически

1

-

char

Низ

16

2

byte

Цяло число

8

1

short

Цяло число

16

2

int

Цяло число

32

4

long

Цяло число

64

8

float

Реално число

32

4

double

Реално число

64

8

Когато една променлива е обявена като представител на клас, ние я наричаме обект или реализация на този клас. Обектът се отличава от основните (вградените) типове променливи по два начина:



  1. Променливата от вграден тип съдържа само данни, докато обектът съдържа данни и методи (т.е може да извършва действия). Списъкът с методите на един клас се нарича интърфейс на класа.

  2. Обектите се записват в паметта по различен начин от вградените променливи (виж фиг.2).

Ние сме ползователи или на вградени класове в JAVA, или на класове написани от други програмисти или на класове написани от нас. Очевидно че можем да напишем класове за конкретна задача, които могат да се ползват от други ползователи. Като пример ще създадем един прост клас:

Първите два реда от класа Square определят двата член-данни на класа т.е. новият тип съдържа два вида вградени данни: цяло число int и знак char. Освен това класът съдържа и един метод, който рисува квадрат. Размерът и пълнежа на квадрата се определят от стойностите на член-данните size и pattern.

За да стартираме и тестваме този клас трябва да го включим в друг клас, който съдържа main() метод както следва:

Изходът трябва да изглежда по следния начин:

* *

* *
* * * * *



* * * * *

* * * * *

* * * * *

* * * * *


& & & & &

& & & & &

& & & & &

& & & & &

& & & & &

фиг.1


Първата команда в метода main() на класа UseSquare създава обект s1 от класа Square. Забележете, че обекти на даден клас се създават с с командата new и конструктора на класа. Втората команда извиква чрез обекта s1 метода draw(), който рисува квдрат с параметрите зададени в класа по подразбиране. След това обектът s1 сменя параметрите и рисува квадрати със съответните нови параметри.

Когато декларираме променлива от вграден тип, компилаторът отделя определно количество памет според вида на типа. Например 1 бит за логическата променлива boolеan, обаче 32 бита за тип int. Когато създаваме обект се отделя памет за всички членове на класа. Например за класа Square се отделя памет от тип int, за променливата size и памет от тип char за променливата pattern. Нека да разгледаме следната програма:





фиг.2


На фиг.2 е показано как се заделя памет и как се променят стойностите в паметта при всяка команда. Първата команда декларира вграден тип променлива х и се присвоява стойност. Втората команда създава обект s1 от тип Square. Променливата s1 сочи към целия обект, не само към определен член. Такъв указател ще наричаме “дръжка”. За да достигнем до члена size на обекта, трябва да използваме името на дръжката и точка.

В четвъртата команда се декларира променлива s2, но не е създаден обект. Това означава че дръжката е създадена, но тя не сочи никъде и има стойност null, а в паметта още няма обект. Ако в този момент се опитаме да достигнем някой от членовете на s2 ще се генерира грешка, понеже членовете на класа още не съществуват. В следващата команда се създава обект с думата new и членовете size и pattern приемат стойностите по подразбиране, определени в класа. След като обектът е създаден лесно се достига до неговите членове.

В Java има специален вграден клас String, който се използва за обработка и анализ на текст. За разлика от другите класове стринговете (низове) могат да се инициалицират директно без да се вика конструктор с командата new:

String name = ”John”;

Разбира се може да се използва и обичайният начин за създаване на стрингов обект както следва:

String name = new String(“John”);

Класът String има много вградени методи. Два полезни метода са следните:


  • Методът length() връща цяло число равно на дължината, броя на знаците в стринга.

  • Методът charAt(i) връща знака на i-та позиция в стринга (позициите започват от 0)

Следният набор от команди:

дава следния резултат:



като променливите в паметта са следните:



фиг.3


Конструкторите са специални методи, които имат за задача да създадат обект и да инициализират членовете-данни. Конструкторите винаги имат името на класа. Конструкторите се извикват с ключовата дума new. Един клас може да има много конструктори, но винаги минимум един конструктор по подразбиране, който е с празни скоби т.е. с аргументите зададени в класа. Ако конструкторът има аргументи, той се нарича конструктор с параметри.

Например в класа Square можем да добавим конструктор с параметри както следва:

Square (int s, char p){

size = s;

pattern = p;

}

Ключовата дума static може да се използва пред член-дата или метод на клас. Тя показва че съответният член или метод принадлежи на класа, а не на отделни обекти на този клас. Статичните членове и методи могат да се достигат (викат) чрез името на класа. Ако се достигат чрез различни обекти те ще имат еднакви стойности, което обезмисля такъв подход. Следният пример обяснява разликата между статичен и не-статичен член.





Изходът от горния код е следния:



Ако сега въведем static преди командата int num =47; изхдът ще бъде следният:



След като променливата num стане статична, тя принадлежи на класа Num, и не е елемент на обектите n1 и n2. Затова ако променим n1.num, n2.num се променя по същия начин, понеже двата обекта се отнасят към една и съща променлива. Обобщавайки можем да кажем, че обектите изразяват нестатичните (т.е. динамичните) компоненти на класа.

Константите са променливи, които не се променят и затова се декларират с ключовите думи static и final. Прието е името на константата да е с главни букви. Например:

static final double CONSTANT=1.2;

Понякога е удобно да имаме клас, който не съдържа променливи, а само методи и константи. В такъв случай е излишно да се създават обекти на класа, понеже те ще бъдат еднакви. Такива методи, които не използват променливи се наричат статични методи. Статичните методи са част от класа, а не част от обекти на класа. Ако са необходими параметри за метода те се задават от потребителя като списък от аргументи в скобите на метода. Пример за статични методи са всички математически функции във вградения клас Math. Затова те се викат чрез името на класа, а не чрез създаване на обекти:

double num=Math.sin(45);

float maximum=Math.max(x,y);
Числово интегриране

Аналитичното интегриране на дадена функция може да изисква съобразителност и ум, но интегрирането с компютър се извършва шаблонно, по избран алгоритъм. Римановата дефиниция за интеграл е границата от сумата на правоъгълни изрезки на функцията когато широчината h на правоъгълниците клони към нула:



(1)

Най-общо алгоритъмът за числово интегриране на функция може да се представи като сумиране на правоъгълни изрезки с различна ширина ωi:



(2)

По принцип сумата в (2) ще дава точния интеграл когато N->∞, но за някои класове от функции резултата е точен и за крайно N. Различните алгоритми за интегриране се различават единствено по това как се избират точките и теглата в сумата (2).

При най-простите методи интеграционния интервал се разделя на еднакви подинтервали т.е. теглата са еднакви ωi= h, а точките хi са разположени еквидистантно (вж.фиг.4). Тези алгоритми включват правилото на трапеца (приближение от първи порядък) и правилото на Симпсон (приближение от втори порядък). Съществуват и по-точни алгоритми за интегриране, при които няма ограничение точките да са еквидистантно разположени, например методите за Гаусова квадратура. Последните методи превъзхождот по точност алгоритмите с еквидистантни точки. Важно е също подинтегралната функция или нейната производна да нямат особени точки в интеграционния интервал. Трудностите с особените точки се избягват като се разбие интеграционния интервал на два или повече подинтервала така че особените точки да станат гранични точки. Друг начин е чрез смяна на променливите.

Фиг.4 Интегралът е площта под кривата f(x) в интеграционните граници от а до b.



1. Правило на трапеца

Нека имаме N равноотстоящи точки в интеграционния интервал [a,b], включително крайните точки т.е. имаме N-1 интервала с дължина:

(3)

Фиг.5 Правило на трапеца

Както се вижда от фиг.5 функцията f(x) се апроксимира с права линия във всеки подинтервал i, така че i-тата изрезка от площта се апроксимира с трапец, откъдето идва названието на метода. Стойноста на функцията f в подинтервала i се взима като средната височина (fi +fi+1)/2. Така площта на един трапец се дава от:

(4)

За да приложим правилото на трапеца за целия интеграционен интервал трябва да сумираме по всички подинтервали и получаваме:



(5)

Вижда се че понеже всяка вътрешна точка се отчита два пъти (има два съседа) нейната тежест е h. Крайните точки се отчитат веднъж и имат тежест h/2.

Според общото представяне (2) теглата в сумата се дават от вектора:

(6)

Грешката при правилото на трапеца е от порядък h2.



2. Правило на Симпсон 1/3

Правилото на Симпсон 1/3 означава че апроксимацията се определя от три точки в два съседни подинтервала. Съществуват по-точни методи на Симпсон, например 3/8, където апроксимацията се определя от 4 точки в три съседни подинтервала. Ние ще се ограничим със стандартното правило 1/3. При това правило (вж. фиг.6) функцията във всеки подинтервал се апроксимира, не с линейна зависимост, както е при трапеца, а с полином от втора степен (парабола):



(7)

За да свържем параметрите α, β и γ с функцията ще разгледаме частния случай когато интеграционния интервал е от -1 до +1. Тогава имаме:



(8)

Фиг.6 Правило на Симпсон

Можем лесно да изразим параметрите α, β и γ чрез стойностите на функцията в двете крайни и в средната точки т.е.

(9)

Следователно имаме:



(10)

От (8) и (10) можем да представим интеграла като претеглена сума от стойностите на подинтегралната функция в три точки:



(11)

Понеже са необходими три точки можем да обобщим резултата (11) за два съседни подинтервала, които се определят от три точки. Така можем да запишем:



(12)

Правилото на Симпсон изисква интегрирането да бъде по двойки съседни интервали, затова общият брой на подинтервалите трябва да е четно число, съответно броят на точките да бъде нечетен. За да приложем правилото на Симпсон върху целия интеграционен интервал, ние сумираме приноса от всички съседни двойки, при което всяка нечетна точка освен първата и последната се отчитат по два пъти. Така получаваме:



(13)

Теглата в сумата на общото представяне се дават от вектора:



(14)

Сумата от теглата е добра проверка за правилноста на интегриране:



(15)

Грешката при правилото на Симпсон 1/3 е от порядък h4. Можем да споменем, че съществува метод на Симпсон с апроксимация с полином от трета степен, наречен правило на Симпсон 3/8. При него грешката е от същия порядък h4, но изчисленията се усложняват , а интервалите трябва да се сумират по тройки. Затова този метод се използва в редки случаи.



Зад. 2.1 Сравнете двата алгоритъма за интегриране: трапец и Симпсон като интегрирате произволен интеграл, примерно функция на експоненциално затихване:

(18)

  • Изчислете относителната грешка за двата алгоритъма:

(19)

Изведете резултатите във файл, подредени в следната таблица:

N T-rule εT S-rule εS
Пробвайте различен брой на извадките N (трябва да са нечетни заради правилото на Симпсон), вариращи от 3 до 501


  • Използвайте MATLAB за да построите логаритмичните зависимости на грешките от броя на точките т.е. функция на log10ε от log10N. Забележете, че грешката на алгоритъма намалява линейно в логаритмичен мащаб докато се достигне грешката на закръгляване на компютъра.


Зад. 2.2 Пробвайте числовите алгоритми за други подинтегрални функции, например

Защо могат да се появят проблеми при изчисляване на интеграла:

Фиг. 7 Логаритмични графики на грешките при различните методи на интегриране на експоненциална функция в зависимост от броя на точките (извадки) при двойна точност (ляво) и единична точност (дясно).
Приложение 1. Конструктор с параметри:

class Square {

int size=2;

char pattern=’*’;

Square(){size=2; pattern = '*';}

Square (int s, char p){ size = s; pattern = p;}

void draw(){

for(int row=1; row<=size;row++){

for(int column=1;column<=size;column++)

System.out.print(pattern);

System.out.println();

}

System.out.println();



}

}

public class UseSquare {



public static void main(String[] args) {

Square s1=new Square();

s1.draw();

s1.size =5;

s1.draw();

s1.pattern = '&';

s1.draw();

Square s2 = new Square(6, '+');

s2.draw();

}

}



Приложение 2. Java примерна програма за интегриране на функцията

f(x)=exp(-x) с метода на трапеците:

//integration by the trapez-rule over f(x)=exp(-x)

import java.util.*;

public class Int_trap {
public static final double A=0., B=1.;//boundaries

//public static final int N=10;//number of points

public static void main(String[] args) {

Scanner sc=new Scanner(System.in);

System.out.println("Enter number of points: ");

int N=sc.nextInt();

double sum, t, w, h;

int i;


h=(B-A)/(N-1);//sample interval(integration step)

sum=0;


for(i=1;i<=N;i++){

t=A+(i-1)*h;

if(i==1||i==N)w=h/2;

else w=h;

sum +=w*Math.exp(-t);

}

System.out.println("number of points="+N);



System.out.println("trapez-rule result="+sum);

double error=sum-1+Math.exp(-1);

System.out.println("trapez-rule error="+error);

}

}



Приложение 3. Java примерна програма за интегриране на функцията

f(x)=exp(-x) с метода на Симпсон:

//calculate integral after the Simpson rule

import java.util.*;//contains Scanner

public class Simpson_integral {

//static final int m=10;//choose even number

static final double A=0., B=1.;

public static void main(String[] args) {

Scanner sc=new Scanner(System.in);

System.out.println("Please enter even number of intervals: ");

int m=sc.nextInt();

while((m+1)%2==0){

System.out.println(m +" is odd. Enter even number.");

m=sc.nextInt();

}

double f[]=new double [m+1];//declare an array



double h=(B-A)/m;

for(int i=0;i<=m;i++){

double x=i*h;

f[i]=Math.exp(-x);

}

double s=simpson(f,h);//declare a method and calculate integral



System.out.println("The number of intervals is="+m);

System.out.println("The Simpson integral is="+s);

double err=s-1+Math.exp(-1);

System.out.println("The Simpson error is="+err);

}//close the main

//define simpson method

public static double simpson(double y[],double h){

int n=y.length-1;

double s0=0,s1=0,s2=0;

for(int i=1;i

s0 +=y[i];

s1 += y[i-1];

s2 +=y[i+1];

}

double s=(s1+4*s0+s2)/3;



//if n is odd number add correction for

//the last slice

//if((n+1)%2==0)

//return h*(s+(5*y[n]+8*y[n-1]-y[n-2])/12);



//else

return h*s;



}//close the method

}//close the class
Каталог: ~tank -> JAVA -> Lectures
Lectures -> Лекция Изключения. Уравнение на КортевегДеВриз
Lectures -> Програма за изчисляване на средна стойност
Lectures -> Лекция аплети и уеб-страници
Lectures -> Лекция Mногонишково програмиране в java понятието нишка (thread) се свързва с контрола или изпълнението на отделна програма или задача. Нишките са опънати във времето и свързват една с друга последователните команди
Lectures -> Програма за изчисляване на средна стойност
Lectures -> Лекция Характерни особености на езика java. Сравнение с други
Lectures -> Приложение Аплети с геометрични фигури. // A java applet displaying a white circle in a black square
Lectures -> Лекция 10. Програмиране в уеб-страница с помощта на Java Script
Lectures -> Лекция Входни и изходни потоци. Писане във файл и четене от


Сподели с приятели:




©obuch.info 2024
отнасят до администрацията

    Начална страница