Как сделать производную в паскале

Добавил пользователь Дмитрий К.
Обновлено: 04.10.2024

Пользовательские процедуры и функции. При написании программ со сложными математическими вычислениями становится очевидным, что математических функций встроенных в Turbo Pascal, явно недостаточно. Нет, например такой функции, как y = x n . В процессе вычислений можно конечно задействовать такую формулу возведения в степень: y := exp(n*(ln(x)); но при частом использовании такой формулы в программе легко запутаться, особенно если нужно использовать разные аргументы.
Turbo Pascal предусматривает создание пользовательских процедур и функций. Рассмотрим создание функции возведения числа х в произвольную степень n (n >=0). Функция на паскале должна быть объявлена до начала программы, то есть до оператора begin.
Функция описывается следующим образом:
function имя функции (аргумент : тип аргумента) : возвращаемый тип данных;
var
раздел локальных переменных (если нужен);
begin
тело функции;
end;
В нашем случае с вычислением степеней, функция будет выглядеть так:
function stepen(x,n: real): real;
begin
stepen:= exp(n*ln(x));
end;
Теперь, напишем программу с использованием нашей функции.
uses crt;
function stepen(x,n: real): real;
begin
stepen:= exp(n*ln(x));
end;
var
rez,osn, pok: real;
begin
clrscr;
write('Wwedi osnowanie');
readln(osn);
write('Wwedi pokazatel');
readln(pok);
rez:= stepen(osn,pok);
writeln('rezultat= ',rez:0:2);
readln;
end.
Результат работы программы:

Используя уже написанные пользовательские функции можно создавать другие функции. Например, в нашем случае, мы можем написать функцию извлечения корня с произвольным показателем k (k <> 0) из любого числа q.
Известно, что q 1/k = q Исходя из этих соображений напишем функцию извлечения корня:
function koren(q,k: real): real;
var
kr: real;
begin
kr:= 1 / k;
koren:= stepen(q,kr);
end;
Так как, функция koren, использует функцию stepen, то в тексте программы, функция koren должна быть описана после описания функции stepen. Дополним и изменим нашу программу, с учётом вычисления не степени, а корня:

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

Дифференцирование функций на паскале

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

На скрине вы видете редактор GNU/Emacs версии 22.0.50.1 (к сожалению, кроме убогого pascal-mode никаких инструментов для паскаля в нем нет. К счастью, gdb и gud теперь поддерживают отладку паскалевского кода в полном обьеме). В нем можете лицезреть код, который дифференцирует произведение и частное. Если у кого-то есть предложения о том, как бы код упростить -- буду рад выслушать.

Все это запущено в kde-3.4 под xorg-x11-6.8.2 в gentoo linux.

ЗЫ. Емакс собран без gtk для улучшения быстродействия.

нееее вот что что а паскаль с динамическими структурами работает очень плоско.Никакой абстракции так сказать. даже скушна как то=(.Ставь себе крышки да следи чтоб во время nil были и усе.

Другое дело с++ такие извращения над динамическими данными мона тварить=). а проще ваще забабахать все в отдельный класс переопределить все операции для класса(что в паскале в принципе не возможно) и работать с твоими дифурами как с динамичиским классом данных :)

> Если у кого-то есть предложения о том, как бы код упростить -- буду рад выслушать.

взять готовую математическую библиотеку и переписать все на с++

сходи лучше сюда

> взять готовую математическую библиотеку и переписать все на с++

не хватало только на c++ фунции дифференцировать :)

> взять готовую математическую библиотеку и переписать все на с++

Я бы рад, но курсач по паскалю.

Ну и конечно, лисп для таких задач подходит лучше всего.

И где тут наши паскалезащитники?

Что за colorscheme? \\ В смысле, что в .Xdresouces ? \\ \\

PS \\ Однако, нашествие имаксеров какое-то! \\ Шучк -- отличный редактор, жаль только, что я vim-ер :)

> Что за colorscheme? \\ В смысле, что в .Xdresouces ? \\ \\

> PS \\ Однако, нашествие имаксеров какое-то! \\ Шучк -- отличный редактор, жаль только, что я vim-ер :)

emacs не редактор, это платформа! :)

кстати, только сейчас заметил darcs-mode

> кстати, только сейчас заметил darcs-mode

Не очень, если честно. Умеет только самое примитивное. С xtla ни в какое сравнение не идет. Собственно из-за xtla я в следующий раз буду юзать arch, а не другую VCS.

За скрин - респект :Emacs+pascal выглядят супер. Теперь такой вот вопросец - наверное уже все заметили по скрину, что Begin в каждой логической скобке перебегает под предыдущую строку - для меня это очень неудобно - я привык структуировть программу выделяя Begin..end отдельно - один под другим - вопрос: Как этого можно добиться в паскаль моде на Emacs? Даже пускай вообще ничего не делает - только бы оставил бы в покое Begin

Да, еще - вот с отладкой тут немного неудобно - что вы используете - gdb?

Да, и еще один минус у FreePascal - у него нет типа Запись :( а мне в курсовом почти 80 процентов всего надо было делать через Записи.


> Да, и еще один минус у FreePascal - у него нет типа Запись :( а мне в курсовом почти 80 процентов всего надо было делать через Записи.

Странно, а у меня есть.

Смерть емаксу, смерть паскалю, смерть КДЕ. Всё остальное порадовало.

Советую немного забыть про лисп и перечитать книгу по паскалю в тем местах где написано про case . of. Также советую сменить стиль трешного кодинга в стиле "напишу ка я все в одну строчку" на более или менее структурированное написание: вроде процедуры и функции в паскле никто не отменял.

Лучше предоставь своё код на паскале, решающий эту задачу. Код на mit-scheme выше по треду. И мы сравним что удобнее.

Давай лучше сравним твой код на схеме и строчку из MathCad-а ? что удобнее ? Глупо сравнивать средство ориентированное на решение задач AI и обработку символьных данных с чисто учебным языком программирования. В плане простоты реализации паскаль абсолютно сольет на этом примере: необходимо писать лексический, синтаксический анализатор выражений, процедуру обработки синтаксического дерева и т.д. В итоге кода будет раз в 40 больше.

Но в плане обучения студентов:

Cкажи чему научится человек написавший такую программу на схеме ? Ответ - примерно ничему. Такая же программа как и все остальные на схеме. Максимум - станет немного лучше владеть схемой. А чему научится человек написавший подобную программу на паскале - многому из того что надо знать относительно принципов построения синтаксических анализаторов. поди еще будет вынужден заглянуть в "дракона" по мере написания.

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

>То есть так? for i:=0 to 5 do begin something1; something2; end;

Возможно не получится точно показать здесь(так как тут довольно интересное форматирование текста получается), но что-то в таком районе

Короче отдельным блоком

Как видно - выше не получилось - отступ от While в 2-3 позиции, а все что внутри - еще отступ уже от Begin\End

> Cкажи чему научится человек написавший такую программу на схеме ? Ответ - примерно ничему. Такая же программа как и все остальные на схеме.

сильно сказано - все программы на схеме одинаковы. не понятно, критика это или нет? :)

предлагаю писать тогда курсовые такого рода на ассемблере, походу ещё можно будет много чему научиться..например написать сначала компилятор си, libc, потом интерпретатор R5RS схемы, ну а потом уж и передрать из sicp'а ту самую программку приведённую выше.

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

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

Я читал эту книгу. Често - ни одного принципиально важного "откровения" не нашел. В приницпе все интересные задачки от туда можно реализовать на том же паскале.

> Советую немного забыть про лисп и перечитать книгу по паскалю в тем местах где написано про case . of.

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

Можно конечно от названий функций перейти к их номерам, но мне облом запоминать таблицу 30 функций.

> Также советую сменить стиль трешного кодинга в стиле "напишу ка я все в одну строчку" на более или менее структурированное написание: вроде процедуры и функции в паскле никто не отменял.

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

Когда пишешь мессагу, можно выбирать способ форматирования. Выбирай "Preformatted text"

> В приницпе все интересные задачки от туда можно реализовать на том же паскале.

не спорю, а ещё можно на vb :)

От слов VB я должен содрагнуться в ужасе ? Впринципе, опять таки повторюсь, паскаль вполне нормальный язык для обучения на котором просто и без лишних заморочек реализуется множетсво задач. Касательно кода на скриншоте - судя по стилю написания это скорее кривая непродуманная реализация, нежели принципиальный глюк языка.

> Имхо дифференцирование - это одна задача, а разбор - другая

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

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

Слушай умник, напиши свою реализацию. Слабо? Или только пространно о неполноценности других рассуждать можешь?

ЗЫ. Считай что парсер и принтер у тебя есть.

> От слов VB я должен содрагнуться в ужасе ? Впринципе, опять таки повторюсь, паскаль вполне нормальный язык для обучения на котором просто и без лишних заморочек реализуется множетсво задач. Касательно кода на скриншоте - судя по стилю написания это скорее кривая непродуманная реализация, нежели принципиальный глюк языка.

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

схемного кода аналогичного по стилю приведённому на скрине не существует. :)

Осталось прикрутить к этой фигне грамотный анализатор s-expr на предмет дифференицируемости. Фактически это трансляция из одного дерева в другое. По идее ничего сложного быть не должно.

> Осталось прикрутить к этой фигне грамотный анализатор s-expr на предмет дифференицируемости. Фактически это трансляция из одного дерева в другое. По идее ничего сложного быть не должно.

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


Дифференциирование - ерунда. Вот попробуй грамотно упростить полученное выражение.

Проверять следующим:
sin^2(x) + cos^2(x)
x+x-x
x+x

Ну и так далле по известным формулам.


Я тоже 2 года назад чё-то ковырял подобное в delfi. В итоге поставили 4 - не удовлетворило упрощение. Кстати есть такой язычок очень неплохой для символьной обработки данных - ICON.

> Дифференциирование - ерунда.

Да, ерунда. Согласен. Цель этого скрина показать насколько геморойно такая ерунда реализовывается на паскале.

А для упрощения выражений нужен вообще pattern matching. В общем, проще написать интерпретатор лиспа на паскале и не мучаться :)

и какой там алгоритм просто грамотный обходчик исходного дерева. вид примерно такой:

для аргументов формы :

Если дифф. число, то результат его дифф =0 Если дифф. переменную, то результат =1 Если аргумент s-выражение, проверяешь есть ли среди его вершин-аргументов переменная, если есть - дифференцируешь в соотвествии с правилами для данной функции, в противном случае результат равен нулю.

Например для (+ x 1) код должен быть таким

function Diff (. ) : PSExpr

if CheckForVarible(P) then .

if P^.funcName = Plus then Diff:=MakeSum(Diff(Arg(1,P)),Diff(Arg(2,P))); .

В конце конечно получится кривое выражение, которое можно упростить выполнив все возможные действия. Для этого можно написать простенький интерпертатор SExpr

Черт, вот представляешь у меня такой же алгоритм. В суд подавать за плагиат надеюсь не будешь?

В общем, жду от тебя работающего кода. Забей на упрощение. Просто дифференцирование. Если будет принципиально лучше моего, то я признаю свою неправоту. Договорились?

ЗЫ. Еще не забудь о том как дифференцируется f(x)^g(x).

Окей. Деньги за клепание тебе курсача переведешь через ВебМани я полагаю ?

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

Я уверен что у тебя такая же бодяга и в парсере s-expr.

> Окей. Деньги за клепание тебе курсача переведешь через ВебМани я полагаю ?

Не съезжай. Мне твой код нафиг не нужен. Для меня понятие "честность" не пустой звук.

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

Юзать парсер секспов внутри программы -- это уже костыль. Если уж делать так, то надо делать интерпретатор диалекта лиспа, так будет ИМХО гораздо логичней, чем мешать лисп и паскаль в одну кучу.

_принципиально_ другой подход к кодированию данного алгоритма.

Приницпиально иной подход к кодированию это внушение компьютеру усилием мысли ?

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

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

В том что ты родил такого монстра виноват ты сам скорее всего.


> Сам написал, что скрин показывает "насколько легко и приятно работать в паскале с динамическими структурами данных." Я тебе отвечаю не с позиций "паскаль круче лиспа при решении задачи символьного дифф.", а с позиции что твой код не является образцом того как правильно работать со структурами данных в паскале. Из-за выбора неправильных решений на уровне реализации твой код превратился в месиво

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

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

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

Все типы данных делятся на две большие группы скалярные (простые) и структурированные (составные). Скалярные типы в свою очередь подразделяются на стандартные (базовые) и пользовательские (производные от базовых типов). Базовые типы предлагаются разработчиками языка.

Базовые типы не требуют предварительного определения. Для каждого типа существует ключевое слово, которое используется при описании переменных, констант и т. д. Если же программист определяет собственный тип данных, он описывает его характеристики и сам дает ему имя, которое затем применяется точно так же, как имена стандартных типов. Язык PASCAL представляет средства определения новых типов, производных от базовых типов. Такие типы иначе называются пользовательскими. Производные типы образуются из уже известных нам типов, наследуя связанные с ними значения и операции. Из простых типов к пользовательским относятся перечисляемый и интервальный типы. Типы данных, конструируемые программистом, описываются в разделе type по следующему шаблону:

type Lat = 'a' .. 'z', 'A' .. 'Z';

Базовые типы данных являются стандартными, поэтому нет нужды описывать их в разделе type. Однако при желании это тоже можно сделать, например, дав длинным определениям короткие имена. Скажем, введя новый тип данных

type Int = Integer;

можно немного сократить текст программы.

Стандартные конструируемые типы также можно не описывать в разделе type. Однако в некоторых случаях это всё равно приходится делать из-за требований синтаксиса. Например, в списке параметров процедур или функций конструкторы типов использовать нельзя.

В языке программирования высокого уровня PASCAL предлагаются следующие базовые типы: целочисленные, вещественный, логический, символьный и адресный;

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

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

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

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

function powers (n: integer) : integer;

var i, sum:integer;

write ('Сколько чисел нужно cложить?');

writeln ('сумма квадратов ',e,' чисел');

writeln ('Число членов = ',e,'. Сумма = ',f);

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

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

Например: function powers (n:integer):real;

Здесь имя функции – powers, у нее один формальный параметр – n, принадлежит типу integer. Функция возвращает результат типа integer.

За заголовком функции следует объявление локальных переменных подпрограммы.

Например: var i, sum:integer;

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

За объявлениями, если они есть, следует пара ограничителей begin-end, окружающих набор предложений, составляющих саму функцию. При этом самым последним должно быть выполнено предложение, которым имени функции назначается некоторое значение, оно будет возвращено в главную программу.

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

Между функцией и процедурой имеется несколько различий. Наиболее существенное состоит в том, что функция всегда возвращает одно конкретное значение, тогда как процедура нет. Это различие отражается в особенности объявления процедур и функций.

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

Пример: procedure test (a: real; var b: integer);

где test – заголовок процедуры, параметр – a типа real, параметр b типа integer.

Вызов процедуры из главной программы представляет собой просто имя процедуры со списком аргументов. Например: test (x,y). Процедуры вообще могут не иметь параметров.

Например, сумма n первых натуральных чисел:

program primer; // процедура без параметров

var a,k,sum : integer;

writeln(a ,' чисел, сумма ',sum);

writeln('последовательное сложение натуральных чисел');

write('сколько первых натуральных чисел сложить? ');

Пример решения задач из Электронного задачника:

Program Proc1; // процедура с параметрами

procedure powerA3(a:real;var b:real);

writeln('Вычисление 3-й степени числа:');

writeln(3-я степень числа:',c:2:1);

Program Proc3; // процедура с параметрами

procedure Mean(x,y:real;var AMean,GMean:real);

writeln('Введите числа a,b,c,d');

program Proc16; // функция

if x=0 then sign:=0;

if x>0 then sign:=1;

writeln ('vv a i b');

writeln ('sign(a)+sign(b) = ',sign(a)+sign(b));

program Proc17; // функция

var a1, b1,c1:real;

if d=0 then RootsCount:='один корень';

if d>0 then RootsCount:='два корня';

writeln ('введи коэффициенты квадратного уравнения a, b,c');

Наберите и отладьте следующие программы, разберитесь в их работе:

1. Программа "Неповторяющиеся случайные числа" с использованием массива и процедуры без параметров.

q:array[1..15] of integer;

if a=b then continue;

if q[a]=q[b] then begin q[a]:=random(20); qw; end;

2. Проверка целого числа на четность (использование функции).

if (n mod 2)= 0 then Chet:=TRUE else Chet:=FALSE;

writeln('Введите целое число и нажмите Enter');

writeln('Для завершения введите 100');

then writeln( m,' - четное число')

else writeln( m,' - нечетное число ');

3. Вычисление длины и площади окружности (использование процедуры с параметрами).

writeln('Вычисление длины окружности и площади круга:');

write('Задайте радиус и нажмите Enter ');

writeln('Радиус окружности: ',t:3:1);

writeln('Длина окружности: ',l:3:1,',площадь: ',s:3:1);

Выполните задания с Proc2 по Proc15 по электронному задачнику (стр.37) и с Proc18 по Proc22 по электронному задачнику (стр.39). Открыть его можно в режиме Помощь – Электронный задачник РТ.

Читайте также: