Смекни!
smekni.com

Объектно-ориентированное программирование 2 (стр. 2 из 3)

для

обеспечения собственной эффективности (даже если он "программист-одиночка").

"Кто ясно мыслит, тот ясно излагает".

К сожалению, среди разработчиков всегда были люди, которые создание запутанных программ (как они сами говорят, "изощренных") ставили себе в заслугу. Однако при ближайшем рассмотрении чаще всего оказывалось, что они запутывают не только окружающих, но и себя.

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

Надо сказать, что в аспекте данной проблемы работа современных программистов по сравнению с порой двадцатилетней давности в чем-то упростилась, а в чем-то усложнилась. Например, возможность использования длинных имен сильно упростила самодокументирование программ. Однако событийная модель приложения, с одной стороны, реализовала интуитивно понятную структуру программы, с другой — привела к появлению огромного числа небольших процедур, ориентироваться в которых не так-то просто. (Последнее усугубляется весьма слабым механизмом навигации по компонентам проекта, например в том же Visual Basic.)

Тут также следует вспомнить, что ранее программы имели лишь один уровень компонентов — процедуры (подпрограммы, функции). Однако еще в середине 80-х (например, в QuickBasic) появился еще один уровень — модули, которые стали состоять из набора процедур и внутренних переменных модуля. (Точнее, ранее понятие "модуля" было эквивалентно "процедуре" — в одном модуле могла находиться лишь одна процедура). Это, конечно, повышает гибкость разработки приложения, однако сразу возникает непростая задача оптимального распределения процедур по модулям.

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

Эффективность.

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

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

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

Введение.

Когда компьютеры были большими, память у них была маленькой и
быстродействие тоже. И поэтому гуру от этих ЭВМ ничего, кроме ассемблера (автокода) и не признавали. И на программистов смотрели свысока - писать, мол, эффективные программы не умеют, только зря машинное время расходуют.

И действительно, как было не признать! Пока программа небольшая и в память помещается — ладно, живите и радуйтесь! А как больше стала? Тут-то и придется признать свое бессилие.

Вряд ли кто-нибудь из нынешнего поколения слышал про "самоубийство программ". Нет, это не стирание EXE-файла во время его работы. Это когда программа во время своей работы использует память, занятую своими командами (которые уже отработали и больше не потребуются) под свои данные. Вряд ли кому-нибудь придется этим сейчас
заниматься. А вот когда у Вас всего 18 Кбайт, то и таким не пренебрегали.

Потом компьютеры стали больше. И в размерах и память с быстродействием тоже росли.

Например, ЕС-1022. Памяти там было уже 512 Кбайт, 100 из них занимала ОС. Остальные 400 делились между 3-4 одновременно работавшими программами разных пользователей. Так что на тех, кто заказывал больше 200 Кбайт, на ВЦ смотрели довольно косо — за наш счет ведь!

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

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

"По координатам точки и вершин треугольника определить, принадлежит ли точка этому треугольнику".

Начнем с того, каким образом это вообще можно сделать. Есть как минимум два варианта решения этой задачи.

Вариант первый.

Дан треугольник ABC и искомая точка X. Чтобы определить принадлежит ли точка треугольнику нужно проделать следующие действия:

1. Найти площадь треугольника ABC.

2. Найти площади треугольников ABX, BCX и ACX.

3. Сравнить. Если площадь треугольника ABC равна сумме площадей ABX, BCX и ACX, значит точка принадлежит треугольнику, иначе - нет.

Второй вариант.


Ситуация такая же: ABC - треугольник, X - точка.

1. Находим площадь треугольника ABC.

2. Находим расстояние от точки X до каждой из вершин треугольника.

3. Выбираем наименьшее из них. (В данном случае BX)

4. Находим площадь треугольника с новой точкой вместо ближайшей. (Здесь XC)

5. Сравниваем. Если площадь первого треугольника больше площади второго, значит, точка не принадлежит треугольнику, иначе - принадлежит.

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

Поэтому подробно рассмотрим только первый вариант.

Выбор пути решения ясен. В любом случае в обоих случаях ответ находится через площадь. А как найти площадь по координатам точек? Ответ есть. Существует такая формула Герона.

Квадратный корень из p(p-x)(p-y)(p-z)

Где p - полупериметр, x,y и z - длины сторон. Длину сторон же находятся по формуле длины вектора.

Первые строчки кода выглядят так:

program Treugolnik;
var q,w,p,ax,bx,cx,dx,ay,by,cy,dy:real;
per1,per2,per3,per4:real;

Переменные q,w промежуточные. В них будут храниться временные значения координат. Переменные ax,bx...cy,dy - координаты вершин треугольника и искомой точки. Переменные per1...per4 и p будут служить для хранения площадей треугольников.

Сначала напишем процедуру получения координат с клавиатуры. Она выглядит так:

procedure Zapoln;
begin
write('Koordinaty A ');
readln(ax, ay);
write('Koordinaty B ');
readln(bx, by);
write('Koordinaty C ');
readln(cx, cy);
write('Koordinaty D ');
readln(dx, dy);
end;

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

Теперь получим их площади.

procedure Ploshad(n:integer);
var d1,d2,d3,per:real;
begin
d1:=sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by));
d2:=sqrt((cx-bx)*(cx-bx)+(cy-by)*(cy-by));
d3:=sqrt((ax-cx)*(ax-cx)+(ay-cy)*(ay-cy));
per:=(d1+d2+d3)/2;
per:=sqrt(per*(per-d1)*(per-d2)*(per-d3));

if n=1 then per1:=per else
if n=2 then per2:=per else
if n=3 then per3:=per else
if n=4 then per4:=per;
end;

sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by)) - формула нахождения длины вектора AB. sqrt(per*(per-d1)*(per-d2)*(per-d3)) - та самая формула Герона. Теперь при вызове этой процедуры мы будем указывать номер нужного треугольника. 1 - главный треугольник, 2-4 - треугольники образованные точкой.

Теперь нам нужно найти площади треугольников образованных точкой. Для этого будем временно подставлять вместо координат одной из вершин координаты точки D.

procedure Zamena(x:integer);
begin
if x=1 then
begin
q:=cx;
w:=cy;
cx:=dx;
cy:=dy;
end else
if x=2 then
begin
q:=ax;
w:=ay;

ax:=dx;
ay:=dy;
end else
if x=3 then
begin
q:=bx;
w:=by;
bx:=dx;
by:=dy;
end;
end;

Этой процедуре мы передаем номер операции. Я условно приняла, что нахождение площади ABD - 1, BCD - 2 и ACD - 3. В переменные q и w мы вводим временные координаты точки, чтобы потом можно было их восстановить.

Далее идет собственно сама процедура сравнения.

procedure Sravn;
begin
if per1 = p then
Writeln('Da, tochka prenadlegit treugolniku') else
Writeln('Net, tochka ne prenadlegit treugolniku'); end;

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

Так что нам еще понадобится функция округления до сотых.

function Okrug(z:real):real;
var a:integer;
begin z:=z/10*1000; // После этого в целой части останутся первые 3 цифры