Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Теоретические вопросы _ функция

Автор: Client 11.11.2007 2:12

не могу понять в зависимости от чего Z получает значение в тексте программы.
подскажите почему


uses crt;
label 0; {описываем метку}
var
rez:real;
m,n:longint; {описали глобальные переменные, используемые в программе}
function fact(z: longint): real; {заголовок функции с формальным параметром-
значением, типом}
var
y: real; {описали локальную переменную}
begin
y:=1; {для получения результата необходимо присвоить у значение 1. также
при помощи этого реализуется вычисление 0! и 1!}
while z>1 do {запускаем цикл в обратную сторону, для упрощения опустим
множитель 1}
begin
y:=y*z;
z:=z-1
end;
fact:=y{вычисляем факториал, присваиваем его значение функции}
end; {конец функции}
begin{начало тела программы}
writeln('введите неотрицательные числа'); {для удобства пользователя просим
ввести числа}
0:readln(m,n); {в память вводятся числа}
if m or n <0 then begin
writeln(‘вы ошиблись, вводите неотрицательные числа’);
goto 0 {при ошибке пользователя предотвращаем выдачу неверного результата}
end;
rez:=(fact(m)+fact(n))/fact(m+n); {вычисляется значение данного выражения}
writeln('результат: ',rez) {выводим на экран результаты счета}
readkey
end.


Автор: volvo 11.11.2007 2:38

Z - это формальный параметр, с которым работает подпрограмма.

Ты передаешь в функцию какое-то значение, внутри функции оно доступно под именем Z.

Автор: Client 11.11.2007 3:12

так я же ни где z н присваиваю значение. А Z здесь параметр-переменная или параметр-константа?

Автор: 2ral 11.11.2007 3:23

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

Автор: volvo 11.11.2007 4:01

Цитата
А Z здесь параметр-переменная или параметр-константа?
Просто параметр... Был бы параметр-переменная, его изменение передалось бы в основную программу - этого не происходит. Был бы параметр-константа, ты бы вообще не откомпилировал программу, потому как нельзя менять константу, ты меняешь - значит, не константа...

Цитата
я же ни где z н присваиваю значение.
Повторяю: ты передаешь значение (неважно какое, КАКОЕ-ТО) в функцию? Вот функция ПРИНИМАЕТ его как Z (ты не должен ничего присваивать, за тебя это делает компилятор)

Автор: Client 11.11.2007 11:17

спасибо за помощь
У меня еще вопрос
Почему эти 2 примера работают одинаково

uses crt;
var
x,y:byte;
z:real;
function qw(a:byte):real;
begin
z:=(x+y)*2/y;
qw:=z;
writeln(z:0:9)
end;
begin
clrscr;
write(' vvwdite a i b ');
read(x,y);
qw(x);
writeln(' (x+y)*2/y= ',qw(x):0:13);
readkey
end.


и
Добавлено через 5 мин.

uses crt;
var
x,y:byte;
z:real;
function qw{(a:byte)}:real;
begin
z:=(x+y)*2/y;
qw:=z;
writeln(z:0:9)
end;
begin
clrscr;
write(' vvwdite a i b ');
read(x,y);
qw;
writeln(' (x+y)*2/y= ',qw:0:9);
readkey
end.



Если у кого-нибудь есть материал про функции и процедуры, просьба, дайте ссылку

Автор: Lapp 11.11.2007 11:46

Цитата(Client @ 11.11.2007 7:17) *

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

Автор: Client 11.11.2007 12:20

Цитата
writeln(' (x+y)*2/y= ',qw(x):0:13);

вот здесь опять вызывается функция? или нет

Автор: Lapp 11.11.2007 12:24

Цитата(Client @ 11.11.2007 8:20) *

вот здесь опять вызывается функция? или нет

Да.
Иначе говоря, предыдущий вызов (на отдельной строчке) - лишний.

Автор: Client 11.11.2007 12:40

я вот понимаю функцию так: в теле функции пишем операторы, имени функции присваиваем значение. потом при вызове функции используется ее значение. Вот например я делал программу, там надо найти дату на к дней назад с учетом висогного года. Значит можно сделать функцию логического типа и если год високосный то ей присвоить значение TRUE иначе FALSE. а потом в самой программе при проверке условия просто подтавляем
IF ИМЯ ФУНКЦИИ THEN в феврале 29 дней...
я правильно понял?

Автор: volvo 11.11.2007 13:37

Цитата
я правильно понял?
В основном... Только надо бы еще функции передать год, который ты собрался проверять на високосность, вот тогда будет совсем правильно...

Автор: Client 11.11.2007 18:51

function visgod:longint{хотя можно integer};
begin
if (god mod 4=0) and not((god mod 100=0) and (god mod 400<>0)) then
visgod:=god;
end
Вроде того?

Автор: volvo 11.11.2007 20:53

Я вот тут: http://forum.pascal.net.ru/index.php?s=&showtopic=19970&view=findpost&p=112078
тебе уже показывал, КАК ИМЕННО, а не "вроде того"...

Автор: Client 11.11.2007 22:44

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

Автор: Client 23.12.2007 16:52

у меня еще вопрос

Function f(a:'a'..'z'):boolean;
Почему так нельзя описывать параметры?? Обязательно надо создать свой диапазонный тип??

Автор: volvo 23.12.2007 16:56

Цитата
Почему так нельзя описывать параметры??
Потому что Паскаль (Турбо и Object, помнится, что Extended вроде бы все-же разрешает) не позволяет конструировать типы в заголовках подпрограмм, а ты именно это и пытаешься сделать...

Автор: Client 23.12.2007 17:01

не позволяет конструировать типы в заголовках подпрограмм
Ясно, т.е. можно использовать только уже описанные типы. А вот здесь
procedure(const A: array of mas_type; const size: integer);
при описание массива?? И еще, как еще можно описать параметры, кроме как через VAR,CONST?? или это все способы??

Автор: volvo 23.12.2007 17:18

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

type
T = array of integer;

, то это будет совсем не то, что
procedure p(var arr: array of integer);


Цитата
как еще можно описать параметры, кроме как через VAR,CONST??
Можно вообще без ничего передавать, "по значению". Можно сделать бестиповый параметр:
procedure p(var v);
begin
end;

, тогда туда можно передать все, что угодно (фактически - это указатель (нетипизированный, pointer) на область памяти, занимаемой объектом). Пример использования я приводил здесь: http://forum.pascal.net.ru/index.php?s=&showtopic=20761&view=findpost&p=116319

Автор: Client 23.12.2007 19:21

Спасибо volvo
помог как всегда smile.gif

Автор: Client 22.01.2008 23:45

Можно еще вопрос?
Вот в основной программе можно сделать так

n:=f(z);
А в самой функции f как-нибудь можно написать
k:=f;
Чтоб в К лежало значение этой функции, но чтоб при этом не было рекурсии, чтоб здесь компилятор не просил параметр. Если можно, то как?

Автор: volvo 23.01.2008 0:00

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

Возникает вопрос: а зачем тебе это? Зачем понадобилось внутри функции получать ее же значение? А если оно еще не вычислено до конца, тогда что?

Автор: Client 23.01.2008 0:11

Цитата
Для решения данной проблемы можно описать переменную result
А можно пример, если не трудно?
Цитата
Возникает вопрос: а зачем тебе это?
Например, есть рекурсия по нахождению факториала и мне надо вывести промежуточные значения этого факториала, или одно из значений функции понадобилось 2-3 раза (что-то вроде такого примера, из-за чего и возник этот вопрос).

Автор: volvo 23.01.2008 0:23

Я так и не понял, зачем тебе внутри функции ее же значение понадобилось несколько раз? Ну, ладно...

var i: integer;

function f(value: integer): integer;
var result: integer;
begin
result := value + 30; { <--- Предварительный результат функции }
{ ... }
i := result; { <--- Запоминаем }

{ ... }
result := result * 3; { пришлось еще ДОвычислить }
f := result; { <--- окончательный результат }
end;

begin
writeln('function = ', f(12)); { <--- Печатаем окончательный результат }
writeln('i = ', i) { <--- А это - промежуточный }
end.

Хотя опять же - я бы так делать не стал: во-первый, глобальные переменные не люблю, а во вторых - не могу представить, КАК это может понадобиться. Пример (конкретный, а не "допустим, нам понадобится") - в студию... Что именно понадобится, для чего надо сохранять значение ЭТОЙ же функции???

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

Автор: Client 23.01.2008 0:56

function f(n:integer):byte;
var
k:byte;
begin
k:=0;
repeat
n:=n div 10;
inc(k)
until n<=0;
f:=k
end;
Функция подсчета количества цифр в числе.
Цитата
Я так и не понял, зачем тебе внутри функции ее же значение понадобилось несколько раз
Лучше всего завести переменную (в этой функции-К) и делать с ней все что угодно, а потом это значение присвоить функции, но у меня почему-то всегда появляются такие вопросы: А что если так? А что если...
Спасибо за пример и обяснение good.gif

Автор: volvo 23.01.2008 1:01

Цитата
Функция подсчета количества цифр в числе.
элементарно переписывается вообще без этой самой доп. переменной:
function f(n: integer): byte;
begin
if n < 10 then f := 1
else f := 1 + f(n div 10);
end;
, если что smile.gif

Автор: Client 23.01.2008 11:22

Цитата
если что smile.gif
А так куда лучше yes2.gif
Еще раз СПАСИБО!