Файл: А. Б. Шнейвайс основы программирования.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 06.12.2023

Просмотров: 336

Скачиваний: 6

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
subroutine tstPout2
real(8) :: z=1.234_8; write(*,’(78("=")/T33,a)’) ’ Работа tstPout2:’
write(*,’(" Вывод")’);
write(*,’(" числа kP
F9.3
E11.3
D11.3"$)’);
write(*,’("
EN11.3
ES11.3
G11.4")’); write(*,’(78("-"))’)
write(*,1000) z,’ 0P’,z,z,z,z,z,z write(*,1001) z,’ 1P’,z,z,z,z,z,z write(*,1002) z,’ 2P’,z,z,z,z,z,z write(*,1003) z,’ 3P’,z,z,z,z,z,z write(*,1004) z,’ 4P’,z,z,z,z,z,z write(*,2002) z,’-2P’,z,z,z,z,z,z write(*,2001) z,’-1P’,z,z,z,z,z,z
1000 format(f6.3,2x,a,1x,0P,f9.3,1x,e11.3,1x,d11.3,1x,en11.3,es11.3,1x,g11.4)
1001 format(f6.3,2x,a,1x,1P,f9.3,1x,e11.3,1x,d11.3,1x,en11.3,es11.3,1x,g11.4)
1002 format(f6.3,2x,a,1x,2P,f9.3,1x,e11.3,1x,d11.3,1x,en11.3,es11.3,1x,g11.4)
1003 format(f6.3,2x,a,1x,3P,f9.3,1x,e11.3,1x,d11.3,1x,en11.3,es11.3,1x,g11.4)
1004 format(f6.3,2x,a,1x,4P,f9.3,1x,e11.3,1x,d11.3,1x,en11.3,es11.3,1x,g11.4)
2002 format(f6.3,2x,a,1x,-2P,f9.3,1x,e11.3,1x,d11.3,1x,en11.3,es11.3,1x,g11.4)
2001 format(f6.3,2x,a,1x,-1P,f9.3,1x,e11.3,1x,d11.3,1x,en11.3,es11.3,1x,g11.4)
end
==============================================================================
Работа tstPout2:
Вывод числа kP
F9.3
E11.3
D11.3
EN11.3
ES11.3
G11.4
------------------------------------------------------------------------------
1.234 0P
1.234 0.123E+01 0.123D+01 1.234E+00 1.234E+00 1.234 1.234 1P
12.340 1.234E+00 1.234D+00 1.234E+00 1.234E+00 1.234 1.234 2P
123.400 12.34E-01 12.34D-01 1.234E+00 1.234E+00 1.234 1.234 3P
1234.000 123.4E-02 123.4D-02 1.234E+00 1.234E+00 1.234 1.234 4P 12340.000 1234.E-03 1234.D-03 1.234E+00 1.234E+00 1.234 1.234
-2P
0.012 0.001E+03 0.001D+03 1.234E+00 1.234E+00 1.234 1.234
-1P
0.123 0.012E+02 0.012D+02 1.234E+00 1.234E+00 1.234
Видим, что
1) при сочетании с дескриптором F результат вывода действительно представляет произведение выводимого числа на 10
k
;
2) при сочетании с форматами E и D масштабный множитель никак не влияет на величину выводимого числа, НО влияет на форму его представления — сдвигает десятичную точку при положительном k и зарабатывает дополнительные нули в мантиссе числа при отрица- тельном (иногда это может пригодиться);
3) форматы же EN, ES и Gw.d при выводе попросту игнорируют масштабный множитель.
297
subroutine tstPinp real(8) x, z write(*,’(78("=")/T33,a)’) ’ Работа tstPinp:’
x=5.678_8
write(*,’("
Ввод")’);
write(*,’(" числа kP
F9.3
E11.3
D11.3"$)’);
write(*,’("
EN11.3
ES11.3
G11.4")’); write(*,’(78("-"))’)
read(*,’( 0p,f11.3)’) z; write(*,2000) x,’ 0P’, z,z,z,z,z,z read(*,’( 1p,f11.3)’) z; write(*,2000) x,’ 1P’, z,z,z,z,z,z read(*,’( 2p,f11.3)’) z; write(*,2000) x,’ 2P’, z,z,z,z,z,z read(*,’( 3p,f11.3)’) z; write(*,2000) x,’ 3P’, z,z,z,z,z,z read(*,’( 4p,f11.3)’) z; write(*,2000) x,’ 4P’, z,z,z,z,z,z read(*,’(-4p,f11.3)’) z; write(*,2000) x,’-4P’, z,z,z,z,z,z read(*,’(-3p,f11.3)’) z; write(*,2000) x,’-3P’, z,z,z,z,z,z read(*,’(-2p,f11.3)’) z; write(*,2000) x,’-2P’, z,z,z,z,z,z read(*,’(-1p,f11.3)’) z; write(*,2000) x,’-1P’, z,z,z,z,z,z
! Форматы вывода:
2000 format(f6.3,2x,a,1x,f9.3,1x,e11.3,1x,d11.3,1x,en11.3,es11.3,1x,g11.4)
end
==============================================================================
Работа tstPinp:
Ввод числа kP
F9.3
E11.3
D11.3
EN11.3
ES11.3
G11.4
------------------------------------------------------------------------------
5.678 0P
5.678 0.568E+01 0.568D+01 5.678E+00 5.678E+00 5.678 5.678 1P
0.568 0.568E+00 0.568D+00 567.800E-03 5.678E-01 0.5678 5.678 2P
0.057 0.568E-01 0.568D-01 56.780E-03 5.678E-02 0.5678E-01 5.678 3P
0.006 0.568E-02 0.568D-02 5.678E-03 5.678E-03 0.5678E-02 5.678 4P
0.001 0.568E-03 0.568D-03 567.800E-06 5.678E-04 0.5678E-03 5.678
-4P 56780.000 0.568E+05 0.568D+05 56.780E+03 5.678E+04 0.5678E+05 5.678
-3P
5678.000 0.568E+04 0.568D+04 5.678E+03 5.678E+03 5678.
5.678
-2P
567.800 0.568E+03 0.568D+03 567.800E+00 5.678E+02 567.8 5.678
-1P
56.780 0.568E+02 0.568D+02 56.780E+00 5.678E+01 56.78
Выводы:
1. Прежде чем пользоваться дескриптором kP необходимо тщательно ознакомиться с нюансами работы его сочетания с нужным числовым дескриптором при вводе и выводе.
2. Без особой нужды масштабный множитель НЕ ИСПОЛЬЗУЕМ.
3. Дескриптор масштабный множитель может встретиться в чу- жих программах. Поэтому важно составить о нём своё собственное мнение. С этой целью полезно разобрать результаты, получаемые приведённой выше программой.
298


8.4
Ещё раз о вводе-выводе данных, управляемом списком
1. Ввод-вывод, управляемые списком, обслуживаются операторами
1
read(*,*) список_ввода write(*,*) список_вывода
2
read *, список_ввода print *, список_вывода
В отличие от первых вторые изначально нацелены на работу с экра- ном. Поэтому им не нужно явно указывать устройство, с которым они должны работать. Так что смысловая нагрузка их единственной
* — та же самая, что в первых двух у второй. Поэтому, если данные вводятся с экрана или через перенаправление стандартного ввода,
то удобнее read *, список_ввода
(для вывода print *, список_вывода
).
2. Мы же с самого начала привыкали работать с первыми двумя, что- бы первая * напоминала об их более общем характере (именно, вме- сто первой * можно указывать и номер устройства ввода-вывода).
3. Управление вводом-выводом под управлением списка ввода (или вывода) выгодно тем, что оно не требует жёсткого закрепления дан- ных за позициями записи в файле ввода (или вывода). Данные до- статочно отделять друг от друга либо пробелами (хотя бы одним),
либо запятыми. Например,
program frm21; implicit none; integer :: i, a(5)=(/1,2,3,4,5/), b(5)
character(8) :: s1, s2, s3, s4, s5
read(*,*) s1, a, s2, b, s3, s4, s5
write(*,*)’ s1=’,s1; write(*,*)’
a=’, a; write(*,*)’ s2=’,s2
write(*,*)’
b=’, b; write(*,*)’ s3=’,s3; write(*,*)’ s4=’,s4
write(*,*)’ s5=’,s5
end
Файл с входными данными программы frm21:
’first’, -1, -2, ,-4, ,’second’,10 11
,,,14,123456789 12345678,’
12345’
s1=first
! Вывод a=
-1
-2 3
-4 5
!
s2=second
! frm21.
b=
10 11 4904176 50960944 14
!
s3=12345678
!
s4=12345678
!
s5=
12345
!
299

8.5
Ввод-вывод данных, управляемый NAMELIST-списком
Иногда при вводе (выводе) неудобно перечислять имена данных в списке ввода (вывода). Можно сопоставить списку имя через оператор namelist и указать это имя в операторе ввода (вывода).
program frm22; implicit none; real(8) a, b, y(5)
integer n, i namelist /my_list/ a, b, n, y; read(*,my_list); write(*,my_list)
write(*,’(5f6.2)’) y;
end
Пример 1 (содержимое файла с входными данными к программе frm22):
&my_list n=3, a=1.0,
b=5.0, y(1:3)=3*0.25d0, y(4:5)=2*7.1d0 /
Пример 2 (содержимое файла с входными данными к программе frm22):
&my_list a=1.0, n=3, b=5, y(1:3)=3*0.25d0, y(4:5)=2*7.1d0
$end
Пример 3 (содержимое файла с входными данными к программе frm22):
&my_list b=5.0, y(1:3)=3*0.25d0, n=3, a=1.0, y(4:5)=2*7.1d0
&end
Файл с выходными данными примера 1
&MY_LIST
A=
1.00000000000000
,
B=
5.00000000000000
,
N=
3,
Y= 3*0.250000000000000
, 2*7.10000000000000
,
/
0.25 0.25 0.25 7.10 7.10
Порядок ввода значений через именованный список my_list безразли- чен. и даже допускает во вводимом файле указывать значения не всех переменных, входящих в него, а только нужных.
Завершение файла с данными, вводимыми по имени namelist-списка,
gfortran допускает тремя способами:
1) дробной чертой “/” (что проще всего);
2) значком доллара “$”, за которым следует end;
3) значком амперсанда “&”, за которым следует end.
В качестве примеров файлов ввода приведены все три варианта.
300


9
Контрольная работа №2
Моделирование работы разностной машины Чарльза Бэббиджа.
9.1
Справочная информация
9.1.1
Исторический экскурс
В Европе конца XVIII начала XIX веков широкое распространение полу- чили арифметические, тригонометрические, логарифмические, астроно- мические и навигационные таблицы (см., например,
[19]). Последние были особенно важны для мореплавания. Вычислялись они вручную и содержали множество совершенно недопустимых ошибок и опечаток.
Французский математик Гаспар Клэр Франсуа Риш маркиз де Прон´
и
(1755-1839) организовал расчёт морских таблиц особым образом. Он рас- пределил вычислителей на три группы. В первую входили пять-шесть выдающихся математиков того времени (в частности, М. Лежандр), ко- торые выбирали наиболее подходящие схемы расчёта и соответствующие формулы. Вторая группа (семь-восемь очень опытных и высококвали- фицированных вычислителей) по этим формулам вычисляли требуемые таблицы с крупным шагом по аргументу. Третья группа (около 90 чело- век) — вычислители низкой квалификации. Их задача состояла в уплот- нении таблиц, т.е. в заполнении интервалов между строками, вычислен- ными второй группой. При этом формулы, по которым третья группа вела расчёт, содержали арифметическую операцию только одного вида
— операцию сложения.
Чарльз Бэббидж (1791-1871), английский математик, инженер и изоб- ретатель, высоко оценил проект графа де Прон´
и и предложил заменить третью группу вычислителей машиной. Машина, предложенная и по- строенная Бэббиджем, вычисляла значения многочлена (полинома) по способу разностей (отсюда и название машины — разностная).
301

9.1.2
Математическая основа алгоритма
Ознакомимся с математической идеей способа на примере расчёта табли- цы значений функции x
4
. Для упрощения возможности устной проверки положим, что табулирование нужно провести для натуральных значений аргумента x = 1, 2, 3, 4, · · · (для машины это не принципиально). Пусть такая таблица уже вычислена (см. колонки (1)-(2)):
(1)
(2)
(3)
(4)
(5)
(6)
1 1
15 2
16 50 65 60 3
81 110 24 175 84 4
256 194 24 369 108 5
625 302 24 571 132 6
1296 434 24 1105 156 7
2401 590.
1695 8
4096
Вычтем из каждого последующего значения столбца (2) предыдущее,
записывая результаты (первую разность) в столбец (3). Повторив анало- гичную операцию с первыми разностями, найдём вторые разности, по- мещая результат в столбец (4). Аналогично запишем третьи разности в столбце (5), и четвёртые в столбце (6). Видим, что четвёртые разности постоянны. Это не случайность, а следствие важной теоремы:
« Если функция есть многочлен (полином) n-ой степени, то в таблице с постоянным шагом по аргументу её n-е разности постоянны»
n-е разности c постоянным шагом по аргументу для полинома n-ой степе- ни характеризуют поведение его n-ой производной, которая равна произ- ведению n! · p
0
, где p
0
— коэффициент при старшей степени аргумента.
302


Случай A.
Поместив разности 15, 50, 60, 24 (нисходящая диагональ) в строку c начальными значениями аргумента и функции, можно, исполь- зуя только операцию сложения, получить содержимое второй строки:
1 + 15 = 16, 15 + 50 = 65, 50 + 60 = 110, 60 + 24 = 84,
т.е. значение 2 4
= 16 и все необходимые для дальнейшего расчёта разно- сти 65, 110, 84 (последняя, четвёртая разность остаётся неизменной).
(1)
(2)
(3)
(4)
(5)
(6)
1 1
15 50 60 24 2
16 65 110 84 24 3
81 175 194 108 24 4
256 369 302 132 24 5
625 571 434 156 6
1296 1105 590 7
2401 1695 8
4096
Вводимые параметры программы: n — порядок полинома; a и b —
начальный и конечный аргументы таблицы; m — количество строк таб- лицы, которые хотим вычислить; d(-1:n) — полная начальная строка.
Для её расчёта надо знать n + 1 первых значений полинома.
Случай Б.
Схема Бэббиджа позволяет разместить в начальной строке разностной таблицы разности, получающиеся не только по нисходящей диагонали, но и по соответствующей восходящей. Например, если в на- чальную строку таблицы поместить соответственно
7, 2401, 1695, 590, 156, 24,
(2401 = 7 4
), то получить значение 8 4
= 4096 можно прибавив к 2041
значение первой разности 1695. В этом случае расчёт разностей придёт- ся вести в направлении убывания их номеров, в то время как в случае
A расчёт должен был вестись в направлении возрастания их номеров.
(1)
(2)
(3)
(4)
(5)
(6)
7 2401 1695 590 156 24 8
4096 2465 770 180 24 9
6561 3439 974 204 24 10 10000 369 302 132 24 303

Разностная машина Бэббиджа была механической: для представления десятичных чисел использовались регистры, роль которых выполняли счётные колёса; каждой колонке, кроме (1), соответствовал свой регистр,
которых было 7, и каждый хранил числа из 18 десятичных разрядов.
Вычислительная часть машины была связана с печатающим меха- низмом. Результат расчёта автоматически выгравировывался на медной пластинке, которая затем использовалась для получения нужного коли- чества оттисков, причём процесс расчёта текущей строки таблицы сов- мещался по времени с выводом ранее вычисленной.
Строгое постоянство n-ых разностей выполняется только для поли- номов n-ой степени. Однако, многие математические функции могут с высокой степенью точности приближаться полиномами. Именно поэто- му важно знать алгоритмы расчёта полиномов. Теперь мы знаем два из них: схема Горнера (см. домашние задания первого и второго семестров)
и разностная схема машины Бэббиджа.
При сдаче зачёта по задаче №2 важно уметь правильно обосновать ре- зультаты пропуска программы при расчёте полинома x
4
(mp=4, a=1.0,
b=10.0) для следующих значений m:

1   ...   12   13   14   15   16   17   18   19   ...   23

1. m = 9. Почему при m=9 схема Бэббиджа получает точный резуль- тат P(10.0)=10000.000?
2. m = 7. Почему при m=7 результат P(10)=9999.994 менее точен нежели при m=9, хотя количество операций сложения при m=9

больше чем при m=7?
3. m = 72. Почему при m=72 результат P(10)=10000.000 точен?
4. m = 144. Почему при m=144 результат P(10)=10000.001, т.е. абсо- лютная погрешность ≈ 10
−3

, хотя значения всех аргументов табли- цы имеют нулевую погрешность округления, как и в случае m=72?
Вывод каждой строки разностной таблицы выгодно дополнить выводом соответствующих абсолютной и относительной погрешностей значений полинома, вычисленных по схкеме Бэббиджа, взяв в качестве точного результат, полученный по схеме Горнера. Выгода состоит в том, что при изменении mp нет нужды изменять соответственно число цифр ман- тиссы в значении полинома, так как качество точности расчёта легко проследить по значениям абсолютной и относительной погрешностей.
304

9.2
Возможные затрагиваемые темы программирования
1. Одномерный массив (основная). Предполагается, что после зада- ния содержимого начальной строки разностной схемы, потребуется лишь одномерный массив (НЕ МАТРИЦА)
2. Двумерные массивы (дополнительная). Матрицу, например, можно использовать для автоматического расчёта начальной строки (вто- рая задача), хотя проще обойтись одномерным.
3. Линейный связный список. В третьей задаче вместо одномерного вектора требуется использовать связный список для хранения аргу- мента, значения полинома и соответствующих разностей.
4. Форматные дескрипторы a, x (или t), f (или e, или g) и организация наглядного форматного вывода разностной схемы.
5. Внутренний файл. Использование character-переменной в качестве внутреннего файла для моделирования динамического повтори- теля элементов форматной строки. Так, вывод строки разностной таблицы для полинома четвёртой степени требует шесть столбцов,
что при задании формата вывода указывается, например, операто- ром write(*,’(6e12.3)’) (d(i),i=-1,4), где 6 — повторитель форма- та. Не всякий компилятор допускает в качестве повторителя цело- численную переменную. Можно обойтись некоторой целочисленной константой для повторителя, например, 1000. Однако, формировку нужной форматной строки можно поручить программе. Пусть она автоматически вставляет в форматную строку нужное значение по- вторителя (полезное упражнение по ФОРТРАНу).
6. Явное указание интерфейса процедур. В современном ФОРТРАНе берём за правило всегда явно (в частности, модульно) описывать ин- терфейс своих пользовательских процедур, хотя, если не выходить за рамки старого ФОРТРАНа, то этого можно и не делать.
7. Модульное программирование. Обеспечиваем простой переход на иную разновидность типа real. Подключаем механизм перегрузки функций за счёт описания родовых имён модульных процедур, что позволит, например, вызывать по одному имени initial и функцию initial_2 и функцию initial_2l.
305