Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Свитки
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  07:11[Войти] | [Зарегистрироваться]

Некоторые нюансы вывода графиков функций

Алексей Легкунец
дата публикации 14-08-2008 09:27

Некоторые нюансы вывода графиков функций

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

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

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

unit Graf;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;
type
  TForm1 = class(TForm)
    procedure FormPaint(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;

implementation

{$R *.dfm}
 Function f(x:real):real;
begin
f:=2*Sin(x)*exp(x/5);
end;
// строит график функции
procedure GrOfFunc;
var
x1,x2:real; // границы изменения аргумента функции
y1,y2:real; // границы изменения значения функции
x:real; // аргумент функции
y:real; // значение функции в точке х
dx:real; // приращение аргумента


l,b:integer; // левый нижний угол области вывода графика
w,h:integer; // ширина и высота области вывода графика
mx,my:real; // масштаб по осям X и Y 
x0,y0:integer; // точка - начало координат
begin                                           // область вывода графика
l:=10;                                          // X - координата левого верхнего угла
b:=Form1.ClientHeight-20;               //У - координата левого верхнего угла
h:=Form1.ClientHeight-40; // высота
w:=Form1.Width-40; // ширина
x1:=0; // нижняя граница диапазона аргумента
x2:=25; // верхняя граница диапазона аргумента
dx:=0.01; // шаг аргумента

// найдем максимальное и минимальное значения
// функции на отрезке [x1,x2]

y1:=f(x1); // минимум
y2:=f(x1); //максимум
x:=x1;
repeat
y := f (x);
if y < y1 then y1:=y;
if y > y2 then y2:=y;
x:=x+dx; until (x >= x2);
// вычислим масштаб
my:=h/abs(y2-y1); // масштаб по оси Y
mx:=w/abs(x2-x1); // масштаб по оси X
x0:=1;
y0:=b-Abs(Round(y1*my)) ;
with form1.Canvas do
begin              // оси
MoveTo(l,b);LineTo(l,b-h);
MoveTo(x0,y0);LineTo(x0+w,y0);
TextOut(l+5,b-h,FloatToStrF(y2,ffGeneral,6,3));
TextOut(l+5,b,FloatToStrF(y1,ffGeneral,6,3));
// построение графика
x:=x1; repeat
y:=f(x);
Pixels[x0+Round(x*mx),y0-Round(y*my)]:=clRed;
x:=x+dx;
until (x >= x2);
end;
end;


procedure TForm1.FormPaint(Sender: TObject); 
begin
GrOfFunc; end;
// изменился размер окна программы

procedure TForm1.FormResize(Sender: TObject); 
begin
// очистить форму
form1.Canvas.FillRect(Rect(0,0,ClientWidth,ClientHeight));
// построить график
GrOfFunc;
end;
end.

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

Теперь посмотрим, а сколько вычислений значений функции делает программа? В данном случае (25-0)/0.01=2500. Для любого прямоугольника вывода. Чем был обусловлен выбор шага dx? Скорее всего, непрерывностью линии графика. Который, кстати, так и остался прерывистым на некоторых участках, там, где функция меняется быстро. Борются с этим, уменьшая dx, причем чаще радикально — сразу в 10, и даже в 100 раз, доводя до 0.0001; меньше мне не приходилось встречать. А это 250000 вычислений функции. И графики все равно прерывистые. Благо компьютеры быстрые. Но вот если вычислять функцию, заданную неявно, то график будет строится помедленнее. Выберем прямоугольник вывода 600*400. Таким образом по горизонтали мы можем иметь только 600 значений. По оси У, соответственно, тоже. Вопрос: куда идут остальные 249400 результата вычислений? Часть идет на построение вертикальных отрезков прямых, соединяющих соседние ординаты, а львиную долю других поедает Round . Вот тебе и дискретный вывод. Отсюда вытекает, что функцию нужно считать в 600 точках, а отрезки вертикальных прямых можно нарисовать карандашом. И dx нужно выбирать в нашем случае (25-0)/600= 0,0416666. График получится самый качественный, какой только возможно получить. Затем, нет необходимости вычислять ее значение дважды .Можно раз, запомнив результат в массиве(Массив имеет размер не более разрешения монитора). В таких условиях скорость вывода не меняется.

Во-вторых, сам метод построения (вычисление значений функции с шагом dx) работает как фильтр, отсекая высокочастотные гармоники, т.е я хочу сказать, что если к функции f(x) добавить что-то вроде g(x)*sin(2*pi/dx*x), то результат вывода будет плачевным. Этот элемент никак не изменит предыдущий график. Хотя он может являться основным носителем информации о функции. И уж конечно очень непросто вывести на экран график дискретной функции (имеется в ввиду универсальными программами общего пользования, подобными приведенной). Если взять f(x)=2*Sin(x)*exp(x/5)+ exp(x*x)*sin(2*pi/dx*x), то данная программа второе слагаемое не заметит, хотя будет тратить время на расчет f(x)=2*Sin(x)*exp(x/5)* exp(x*x)*sin(2*pi/dx*x). А в этом случае график константы. Приведенная программа, как я упоминал, некорректно отобразит и его, но это же учебная программа. Поэтому претензий не предъявляем.

А вот если взять TAB MathGrapher 1.0 (распространена в Интернете) и просто ввести 5* Sin(200*pi*x), то мы получим чистый ноль. Вместо 5, понятно, можно написать любую функцию, да и вместо Sin(200*pi*x) любую периодическую с кратной частотой, и программа выдаст неверный график.

Это, как я уже писал, издержки метода построения. Как с этим бороться? Неэффективный и не исправляющий программу брать dx=0.0037 или что-то наподобие, тогда сложно будет подобрать период и натыкать автора(шутка). Очевидно, нужно, чтобы программа давала возможность рассматривать функцию на небольшом отрезке, с dx=(х2-х1)/w (ширина вывода в пикселях). Т.е. программа должна автоматически менять шаг с уменьшением отрезка. Что-то подобное я написал, в результате можно графическим методом решать умопомрачительные трансцендентные уравнения с точностью 10E-7 и выше за считанные минуты (х2, х1 нужно вводить вручную). Тем, кто над подобным не задумывался, код в руки, а пользователям хотелось бы порекомендовать: не берите программы, которые не меняют шаг. А то в ответственных случаях можно получить неверный график и попасть в затруднительное положение.




Смотрите также материалы по темам:


 Обсуждение материала [ 02-08-2009 19:56 ] 15 сообщений
  
Время на сайте: GMT минус 5 часов

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

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования