Дипломная работа: Финансовые функции и рекурсия
Дипломная работа: Финансовые функции и рекурсия
Министерство образования РФ
Тульский государственный педагогический университет
имени Л.Н. Толстого
Кафедра информатики
Дипломная работа
"Финансовые функции" и рекурсия
Выполнил:
Научный руководитель:
Тула-2000
Введение. 4
Динамика вклада. 7
Задача о величине вклада. 7
Задача о величине вклада после снятия денег в конце каждого
периода 11
Задача о величине вклада после внесения (снятия) денег в
конце или начале каждого периода. 13
Задача о изменяющихся процентных ставках. 15
Задача о изменяющихся процентных ставках и величинах
снимаемых денег 16
Дисконтирование. Инвестиции. Консолидирование. 19
Задача о дисконтировании. 19
Задача о инвестировании проекта. 21
Задача о консолидировании платежей. 23
Платежи. 25
Задача о равных платежах в конце
каждого периода. 25
Задача о платежах с одинаковой
современной стоимостью.. 30
Задача о платежах на проценты.. 31
Разные задачи. 34
Задача о величине процентной ставки. 34
Задача о величине процентной ставки 2. 36
Задача о количестве периодов для расчета заемщика с банком.. 38
Задача о суммарной способности к кредитованию.. 41
Задача о минимальном количестве банков. 42
Задача о изменении величины суммарного кредитования. 43
Заключение. 50
Литература. 51
В
электронные таблицы Excel, систему управления базами
данных Access, язык программирования Visual Basic и многие другие современные
компьютерные технологии встроены так называемые “финансовые функции”: fv(), pv(), pmt(),
ppmt(), ipmt(), rate(), nper() и т.д. В повседневной
жизни с задачами, в которых они могут быть использованы, приходится
сталкиваться достаточно часто. Это заставляет преподавателей информатики
педагогических вузов не только знакомить студентов различных специальностей с
синтаксисом и семантикой этих функций, но и уделять особое внимание поиску
новых методик и технологий обучения, ориентированных на прочное усвоение
соответствующих знаний. И здесь на помощь может прийти рекурсия, с помощью
которой строятся лаконичные и легко понимаемые алгоритмы, а затем и
соответствующие информационные модели в виде рекурсивных программ на том или
ином языке программирования [9, 10]. И что особенно важно, набор упомянутых
финансовых функций и рекурсивные алгоритмы их вычисления могут служить весьма
подходящим фоновым материалом для начального освоения студентами рекурсии как
достаточно общего и эффективного метода решения практических задач.
Заметим, что
вычисление значений финансовых функций с помощью электронных таблиц Excel или других пакетов прикладных программ можно признать
целесообразным лишь при уже полностью сформированном понимании их синтаксиса и
семантики. Но при первом знакомстве с этими и другими функциями рекурсивный
подход в полной мере демонстрирует все свои дидактические преимущества по
сравнению с простым описанием функций и решением по ним соответствующих
прикладных задач. Он дает возможность не только всесторонне понять содержание
излагаемого материала, но сделать это быстро и эффективно. И что особенно
важно, полученные знания становятся достоянием долговременной памяти. Последний
вывод убедительно подтверждается результатами проверочной работы, проведенной в
двух группах студентов через год после ознакомления их с финансовыми функциями.
Результаты эти оказались и удивительными, и убедительными. Более 36 процентов
студентов, которым материал преподносился традиционно, с предъявленным заданием
не справились. В то же самое время в группе, осваивавшей этот же материал с
использованием рекурсии, с заданием не справились лишь 12 процентов студентов
(3 человека). Столь разительное различие в уровне усвоения знаний в
экспериментальной и контрольной группах заставляет нас по-новому оценить
дидактические возможности рекурсии и осознать её роль и место в построении
современного курса информатики в педагогических вузах. И эта роль, по-видимому,
будет возрастать вместе с дальнейшим развитием компьютерной техники и
программного обеспечения. В связи с этим главной задачей данной дипломной
работы является разработка методик решения финансовых задач рекурсивными
методами и их практическая реализация в виде обучающей программы (Web-узла) по данной теме.
При отборе
материала для первоначального знакомства студентов и учащихся с рекурсивными
методами решения прикладных задач, ориентированных на экономические
специальности, существенную роль играют два фактора: наличие экономического
содержания в этих задачах и прозрачность свойств рекурсивности рассматриваемых
в них объектов. И то, и другое в полной мере может быть обеспечено рекурсивной
реализацией финансовых функций.
Большой
выбор содержательных задач, решаемых финансовыми функциями, можно встретить в
сфере банковской деятельности [1,3-6]. Причем возникают они здесь на
обслуживании всего лишь двух операций. Банк, являясь финансовым посредником между
вкладчиками и заемщиками (рис.1), с одной стороны, принимает деньги и платит по
ним проценты, а с другой стороны, дает кредиты и получает за них проценты. Разность
между той суммой, которую получает банк от заемщиков по процентам за конкретный
период, и той, которую он платит вкладчикам по процентам за этот же период, и
составляет прибыль банка. Как говорил американский писатель-сатирик Генри Уилер
Шоу [2, с.30] “Банковский процент не знает ни отдыха, ни богослужений, он
работает и по ночам, и в воскресенье, и даже в дождливые дни”.
|
|
 |
Рис.1. Банк как финансовый посредник между вкладчиками и заемщиками
В
рассматриваемой ниже серии задач везде речь идет об обычных вкладах и сложных
процентах, а решения оформлены в виде рекурсивных программ-функций на языке
программирования вычислительной среды Mathcad. Все они
делятся на три категории: прямые рекурсивные аналоги, частные случаи и
обобщения встроенных в Excel финансовых функций. Для
первой категории функций и их аргументов используются стандартные обозначения. В
иных ситуациях обозначения произвольны. Наличие почти во всех задачах несложно
выводимой при определенных навыках, но обычно громоздкой, конечной
формулы-решения позволяет на контрольных примерах легко проверить правильность
составленных для них рекурсивных программ. Отметим, что все приведенные
программы, благодаря рекурсивности, весьма просты и для их написания не
требуется знания соответствующих конечных формул. В дополнении к данной работе
дается краткое описание Mathcad и
программы Microsoft FrontPage 2000, с помощью которой был создан Web-узел.
Начнем
упомянутую серию задач с рассмотрения простой и многим знакомой житейской
проблемы хранения денег в банке.
Вкладчик положил
в банк сумму в sum денежных единиц под p процентов за один период времени (год,
месяц, неделя и т.д.). Составить программу-функцию, возвращающую величину
вклада по истечении n периодов времени (n = 1, 2, …).
Решение. Пусть
invest(sum,p,n) - искомая функция. Вычисления
значений invest() можно проводить по известной формуле:
invest(sum,p,n) = sum×(1+p/100) n.
Однако в
учебных целях нас будет интересовать рекурсивный вариант алгоритма решения
задачи. Её параметризация реализована в постановке. Рекурсию будем осуществлять
по параметру n. База рекурсии очевидна. В самом деле, если вклад положен на
хранение и взят сразу, то есть до истечения первого периода времени начисления
процентов, то возврату подлежит начальная сумма вклада - sum. Далее, декомпозиция может быть
реализована исходя из следующего факта. Положить некоторую сумму в банк на n
периодов – это то же самое, что положить эту сумму на n – 1 период, взять и
снова положить на 1 период. Соответствующий вариант программы-функции решения
задачи выглядит так:
(1)
Реализуя
декомпозицию иным способом, получим другой вариант рекурсивной программы (1). Например,
сделаем это исходя из такого факта. Положить некоторую сумму в банк на n
периодов – это то же самое, что положить эту сумму на 1 период, взять и снова
положить на n-1
период. Соответствующая программа-функция выглядит так:
(2)
В данной и
подобной ей задачах указанные декомпозиционные посылки программно реализуются
приблизительно с равной степенью сложности и, тем самым, обе имеют право на
существование. Однако может возникнуть ситуация, когда предпочтение должно быть
отдано той или иной конкретной посылке. Например, если в последующем имеется
необходимость перейти к нерекурсивному варианту программы, то лучше
пользоваться посылкой первого типа, а если есть проблемы с доказательством
правильности реализуемого алгоритма, то целесообразно работать с посылкой
второго типа.
Нетрудно
видеть, что общее количество рекурсивных вызовов при вычислении invest(sum,p,n) и invest1(sum,p,n) равно n.
Можно было бы уменьшить это значение до величины floor(log2(n)) +1, где floor(a) - целая часть натурального числа a, исходя из следующих двух декомпозиционных посылок.
Пусть сумма sum=m× g денежных единиц помещена на вклад при ставке в p процентов за период. Тогда через n периодов sum возрастет до той же
самой величины, что и совокупная сумма m отдельных
вкладов по g денежных единиц каждый, также помещенных под
р процентов за период. Не ограничивая общности, величину sum
можно считать целым неотрицательным числом. В противном случае можно было бы
перейти к иному номиналу денежных единиц. Значения m и g также будем считать целыми числами.
Положить
некоторую сумму sum в банк на n периодов – это то же
самое, что положить эту сумму на k (0£k£n) периодов,
взять и снова положить на n-k периодов.
Основанную
на этих посылках рекурсивную функцию для решения задачи 1 обозначим через inv(sum,p,n). Указанные посылки обнаруживают такие свойства этой
функции.
Первая
посылка.

В частности,
при m=1 получаем:

Первая и
вторая посылки. Пусть k=floor(n/2), тогда.


Отсюда при n=2×k сразу же получаем:

При n=2×k+1 имеем:


Выведенные
соотношения для inv() позволяют записать такую
программу для её вычисления:

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

и оно
действительно равно
Контрольные
примеры.


Незначительная
перестройка структуры функции inv(sum,p,n) позволяет получить еще один
вариант её реализации, в котором количество рекурсивных вызовов в точности
равно Сделать
это можно так:

Замечание. В
любых ситуациях, в которых возникают вопросы о быстродействии алгоритма,
желательно по возможности минимизировать общее количество рекурсивных вызовов. В
рассмотренной задаче построить алгоритм с рекурсивными вызовами можно было
бы значительно проще, исходя из конечной формулы для решения задачи и дихотомии.
Однако путь, который мы прошли, имеет свои достоинства. Он позволяет в общем
случае выявить ограничения на рекурсивную функцию, достаточные для столь малого
количества рекурсивных обращений при её вычислении. Фактически, из проведенных
рассуждений вытекает такое утверждение.
Пусть
функция F(a,n,v) удовлетворяет условиям:
F(a,1,v) =g(a,v),
F(a,n,v) =a×F(1,n,v),
F(a,n,v) =F(F(a,k,v),n-k,v) (1£k£n),
где a -
действительное число, n - натуральное число, v=(v1,v2,…,vs) T - вектор с числовыми компонентами,
g(a,v) -
функция, значения которой для a и v из области определения F(a,n,v)
мы вычислять можем. Тогда рекурсивная программа-функция:

вычисляет
значение F(a,n,v) ровно за рекурсивных вызовов.
Доказательство
этого факта с использованием свойств A, B и C можно провести так:
Отсюда, при n=2×k имеем

а при n=2×k+1 получаем


Именно на
этих соотношениях и базируется алгоритм, реализуемый программой-функцией F(a,n,v).
И в
заключение замечания приведем пример функции, удовлетворяющей условиям A, B и С: где в области определения функции
f(v) её значения мы вычислят
умеем.
Вкладчик положил
в банк сумму в sum денежных единиц под p процентов за один период времени. В
конце каждого периода вкладчик после начисления процентов снимает со счета A денежных единиц. Определить сумму вклада через n периодов времени.
Решение. Данная
задача весьма похожа на задачу 1. Рекурсивная программа-функция waste(sum,p,A,n) реализует декомпозицию, исходя
из такого утверждения. Положить сумму sum в банк на n
периодов со снятием в конце каждого периода по A
денежных единиц – это то же самое, что положить данную сумму на тех же условиях
на n – 1 период, взять, снова положить на 1 период и затем снять A единиц.
(3)
Нетрудно
понять, на какую посылку опирается при декомпозиции рекурсивная
программа-функция waste1(sum,p,A,n),
решающая ту же самую задачу о динамике вклада.
(4)
Замечание 1.
Конечная формула для решения задачи 2 выглядит так:

Выводится
она следующим образом.



Одно из
преимуществ “формул” waste() и waste1()
в том, что они выписываются без всякого вывода и практически без затруднений.
Контрольные
примеры.
Замечание 2.
В связи с задачей о динамике вклада может быть поставлен и такой вопрос. Сколько
лет подряд вкладчик может снимать со счета по A денежных единиц в конце каждого
периода после начисления процентов, если он положил в банк сумму в S единиц при
ставке p процентов. Ответ на него может дать рекурсивная функция year(S,p,A):
Здесь случай
неубывания величины вклада выделен отдельно (lo³S),
рекурсия организована по остаткам вклада после периодов, в которых хватило
денег на очередную выплату в A единиц.
Контрольные
примеры.
Вкладчик
положил в банк pv денежных единиц на nper периодов при неизменной банковской ставке
в rate процентов. В дальнейшем он предполагает в конце (type=0) или начале
(type=1) каждого периода вносить (забирать) по pmt денежных единиц. Какой будет
величина вклада через nper периодов?
Решение. Данная
задача является прямым обобщением задач 1 и 2 и может быть решена с помощью
встроенной в Excel функции fv().
Однако нас будут интересовать её рекурсивные аналоги. Будем считать, что знак
величины pmt определяет тип операции, совершаемой
вкладчиком в конце или начале каждого периода. При pmt³0 деньги вносятся на счет, а
при pmt<0 деньги снимаются со счета (в Excel наоборот!). Далее, пусть знак pv
определяет, имеет ли вкладчик деньги на счету или он должен банку. При pv³0
деньги на счету есть, при pv<0 имеется задолженность
в |pv| денежных единиц (в Excel
наоборот!).
Пусть fv(rate,nper,pmt,pv,type) - функция для решения исходной задачи. Ниже
приведено два варианта (fv1(), fv2())
рекурсивной реализации fv():


Дадим
пояснения к функциям fv1() и fv2(),
например, при type=0. Параметризация задачи фактически
осуществлена в её постановке. Базой рекурсии для обоих предложенных вариантов
служит случай nper=0. Иными словами, если pv денежных единиц положить в банк и сразу же их забрать, то
будет возвращена та же самая сумма. Декомпозиция для fv1()
и fv2() проведена, исходя из того, что решение исходной
задачи по конечному результату равносильно соответственно совокупности
следующих действий. Для fv1(): “Положить на тех же
условиях pv денежных единиц в банк на nper-1 период, снять всю сумму с вклада и,
наконец, на тех же условиях снова положить её на один период”. Для fv2(): “Положить на тех же условиях pv
денежных единиц в банк на 1 период, снять всю сумму с вклада и, наконец, на тех
же условиях снова положить её на nper-1 период”. Именно это и реализовано в
соответствующих программах функциях.
При
необходимости можно было бы вывести и конечную формулу для вычисления fv() или, по крайней мере, попытаться найти её в том или ином
справочнике. Но это требует дополнительных усилий и затрат времени. Да и
выглядит формула достаточно громоздко:

В банк
положена сумма в S денежных единиц. Пусть банк проводит
начисления в процентах: в течение n0 периодов - по ставке p0, затем
в течение n1 периодов -
по ставке p1 и т.д. и, наконец, в течение nk-1 периодов - по
ставке pk-1. Считая nj (j=0. . k-1) натуральными числами, вычислить размер
вклада через n0+n1+…+nk-1 периодов.
Решение. Рассмотрим
векторы длин периодов n и процентных ставок p:
n=(n0,n1,…,nk-1) T, p=(p0,p1,…,pk-1) T.
Данная
задача является обобщением задачи 1 и при длине вектора n,
равной единице, совпадает с ней. Пусть revise(S,p,n) - решение задачи 4. Тогда, в силу
сказанного, при length(n) =1 имеем
revise(S,p,n) =invest(S,p,n),
и это
соотношение может служить базой рекурсии. Декомпозицию реализуем, исходя из
следующих соображений. Пусть length(n)
>1 и задача 4 решена для векторов n1 и p1, полученных отбрасыванием последнего компонента соответственно
у векторов n и p. Образовавшийся
при этом новый размер вклада обозначим через sum. Тогда
для получения решения исходной задачи с векторами n и p остается подсчитать сумму, возвращаемую при инвестировании
величины sum на последние nk-1
периодов под pk-1 процентов. Иными словами, необходимо
еще раз решить задачу 1, то есть вычислить значение функции invest(sum,pk-1,nk-1).
Именно эти соображения и использованы при написании функции revise():
Рекурсивная
функция revise1(S,p,n) построена на способе
декомпозиции, вытекающем из таких соображений. Если исходную сумму S инвестировать под p0 процентов на n0 периодов, то с полученной суммой останется решить исходную
задачу для векторов n и p c удаленными первыми компонентами:
Замечание. При
необходимости можно было бы вывести конечную формулу для решения задачи 4. Выглядит
она так:

Контрольные
примеры.
Вкладчик
положил в сбербанк sum денежных единиц под pk (k=0. . n-1) процентов за каждый из n последующих периодов времени. В
конце каждого периода k (k=0. . n-1) после
начисления pk процентов он снимает со счета Ak денежных единиц. Иными словами,
допускается, вообще говоря, и изменение процентной ставки, и величины денежных
единиц, снимаемых с вклада. Составить программы, отвечающие на следующие
вопросы:
Имеет ли
задача решение?
Если задача
имеет решение, то какова величина вклада после n периодов?
Если задача
не имеет решения, то каков наименьший номер периода, в котором взятие
соответствующей суммы оказалось невозможным?
Решение. Рассмотрим
векторы процентных ставок и величин уменьшения вклада:
p=(p0,p1,…,pn-1) T, A=(A0,A1,…,An-1)
T.
Ответ на
первые два вопроса дают рекурсивные программы-функции waste2(sum,p,A) и
waste3(sum,p,A). Если задача имеет решение, то они возвращают величину вклада
после n периодов, а иначе -
отрицательное число. Декомпозиция для функции waste2() проводилась, исходя из
того же утверждения, что и для функции waste(), а декомпозиция для функции
waste3() - исходя из того же
утверждения, что и для функции waste1(). Во втором случае получена более
компактная и ясная программа:


Наряду с
этими программами можно вывести и конечную формулу wa(S,p,A) для расчетов. Пусть n=length(p). Тогда:

И, наконец,
в общем случае:


Контрольные
примеры.

Попробуем
теперь составить программу, отвечающую на третий из поставленных вопросов. Будем
считать, что она должна возвращать вектор с двумя компонентами, который
выглядит так:
[“O’key” решение]
T, если задача имеет решение;
[период сальдо]
T, если задача не имеет решения.
Во втором
случае возвращается период (нумерация от 1 и далее) и отрицательное сальдо
количество денежных единиц, которых недостает для выплаты в данный период.
Всем
перечисленным условиям удовлетворяет рекурсивная программа-функция
waste4(sum,p,A,k):

Здесь k - вспомогательный параметр. При первом
обращении к waste4() его значение должно быть равно
нулю. Далее k используется для организации рекурсивных
вычислений, а операторы return - для
прекращения рекурсивных вызовов при получении решения задачи.
Контрольные
примеры.

Какую сумму
следует внести сегодня в банк при процентной ставке p,
чтобы через n периодов получить S
денежных единиц?
Решение. Фактически
речь идет о вычислении величины, называемой экономистами современной стоимостью
отложенного платежа. Если положить в банк сумму в R=S/(1+p/100) n
единиц, то через n периодов она превращается в S единиц. Та же самая сумма R через n-1 период
превращается в S/(1+p/100) единиц.
Таким образом, если discount(S,p,n) - решение исходной задачи, то при n¹0
имеем:
discount(S,p,n) = discount(S/(1+p/100),p,n-1).
Будем
проводить рекурсию по количеству периодов n. Тогда
последнее соотношение дает нам правило декомпозиции. Отсюда и получаем
программу-функцию (5):
(5)
На вопросе о
том, как проведена декомпозиция в (6), останавливаться не будем:
(6)
Замечание. Из
проведенных рассуждений вытекает, что решение задачи может быть получено по
конечной формуле:

Контрольные
примеры.

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