494 Программирование на языке Си
printf("\n Введите начальное Значение:"); /* Для double: %lf; для long double: %Lf */
/*%1е" - для double; "%Le" - для long double*/ scanf("%f", &s);
if (s <= 0.0)
{
printf("\n Ошибка: начальное Значение < O f ’); return 1;
)
e = s ; do
{/*Цикл с постусловием */ k++;
e /= 2.0; el = s+e;
)
while(el > s && k < Kmax); 4 printf("\n Число итераций: %d", k) ; printf("\n Машинный нуль: %e", e);
/* Для double: %le; для long double: %Le */
}
Программа позволяет обратить внимание на следующие во просы программирования:
•точность представления вещественных данных разных типов;
•возможности макросредств (препроцессорные подста новки);
•спецификации преобразований при форматированном об мене (вводе-выводе) вещественных данных разных типов.
Результаты выполнения программы (для типа float):
Представление вещественных чисел:float
Введите |
начальное Значение: |
1.0 |
Число итераций: |
24 |
Машинный |
нуль: |
5.960464е-08 |
Изменим директиву препроцессора, определяющую препроцессорный идентификатор REAL:
Глава 10. Задачи по программированию |
495 |
Заменим спецификации преобразования: %{ на %If, а %е на %1е (см. текст программы).
В результате выполнения программы получим:
Представление вещественных чисел:double
Введите |
начальное Значение: |
1.0 |
Число итераций: |
53 |
Машинный |
нуль: |
1.110223е-1б |
Затем определим новое значение для REAL:
#define REAL long double
и получим решение той же задачи для вещественных данных типа long double (если в дополнение к REAL изменим специфи кацию формата в scanf() и в printf() на %Lf и %Le).
В программе удачно использованы макроподстановки. В за висимости от значения REAL в функции печати printf(), где стоит макровызов type(REAL), появляется строка "float" либо "double", либо "long double". Последовательность подстановок такая (когда REAL замещается значением float):
type(REAL) -> type(float) -> t(float) -> "float"
Обратите внимание, что если вместо макросов t(z) и type(x) оп ределить, например, один макрос
#def±ne type(x) #х,
то последовательность будет неверной:
•type(REAL) -> "REAL"
Вэтом случае будет печататься не имя типа (например, double), а обозначение REAL.
По результатам выполнения программы заполните следую щую табл. 10.1.
496 |
|
|
|
Программирование на языке Си |
|
|
|
|
|
|
Т аблица 10.1 |
|
Таблица результатов оценок “машинного нуля” |
Значения |
|
Внутреннее представление |
|
S |
|
float |
|
double |
|
long double |
|
К |
M-zero |
К |
M-zero |
К |
M-zero |
1 |
24 |
5.960464е-08 |
53 |
1.110223е-16 |
64 ' |
5.42101 le-20 |
10 |
|
|
|
|
|
|
1000 |
|
|
|
|
|
|
1е-20 1е20
В табл. 10.1: S - начальное значение; К - число итераций; M-zero - оценка машинного нуля относительно значения S.
10.2. И терац ио н ны е методы и ряды
Вычислить m значений заданной функции f(x) на интервале [а,Ь\. Результаты оформить в виде табл. 10.2. Столбцы таблицы: 1 - значение х,; 2 - значение функции fiCxJ, вычисленное с ис пользованием библиотечных функций компилятора; 3 - значе ние функции fi(x), вычисленное с помощью явного разложения в ряд (итерационный процесс до достижения машинного нуля); 4 - M-zero - значение машинного нуля относительно fi(x), т.е. точность вычислений; 5 - количество итераций или количество членов ряда в разложении функции.
Таблица 10.2
Ш |
Точность (M-zero) |
Число итераций |
x 0= a
Глава 10. Задачи по программированию |
497 |
Вычисления проводить для float, double и long double.
Ограничения.
•Переменных с индексами (и массивы) не использовать.
•Факториалы и высокие (больше 2) степени в выражениях для членов ряда в явном виде не применять.
•Количество т точек на интервале [а,Ь] не. меньше 10. Раз биение (расположение точек на оси х) может быть равно мерным либо по предложенному вами правилу (детерми нированному или случайному).
•Для тригонометрических функций в программе приводить значение аргумента к величине 0<=х<=Я/2.
•Для показательных функций выделять целую часть аргу мента, а разложение выполнять для дробной части.
Комментарий по итерационным методам (см.: Трифо нов Н.П., Пасхин Е.Н. Практикум работы на ЭВМ. - М.: Наука, 1982. С. 13-16):
1. Для уравнения у = tfx (х>0, к>0, к - целое) можно запи сать F(x,y) =\-x/}/c=0, откуда получим по формуле Лагранжа:
У п+1= У п
Здесь для начального приближения уя>0 необходимо выпол нение условия у0к<(к+1)х.
Если использовать F(x,y)=у* -х=0, то получим итерационную формулу Ньютона:
У п+1 к (* - 1)У п
У пк - '
справедливую для Нужная точность оценивается соотношением [у^гУп!^, где £
обычно заранее задано. Однако в работе выполнять вычисление нужно с точностью до "машинного^нуля".
498 |
Программирование на языке Си |
2. Для многих функций требуется использование формулы Маклорена (частный случай разложения в ряд Тейлора):
|
|
|
|
|
П |
|
|
|
|
|
|
|
/ |
( |
* |
|
) |
* |
|
|
|
|
|
*=о |
|
|
|
где ик(х)=акхк и коэффициенты таковы: |
|
|
|
|
|
|
|
а2- ф „ . . , , , а1- У т |
|
|
|
|
|
|
2! |
|
Л! |
|
|
Остаточный член: |
|
|
|
|
|
|
|
|
|
|
n+i |
|
|
|
|
|
|
|
Лл(х) = (^71)!/ ( "+')(0х)’ |
(о < 0 < 1 )- |
|
|
Примеры разложения в ряд Тейлора: |
|
|
|
|
3 |
5 |
|
2 п + 1 |
|
+..., |
д: <®, |
у |
= |
sin(x) = х - |
— |
+ —— |
...+(-1)"---------- |
л |
|
w |
3! |
5! |
|
(2л +1)! |
|
|
у |
|
|
х2 |
х 4 |
|
х 2п |
|
X < 00 |
= cos(x) = 1------+ — +...+(-1)л------+..., |
л |
|
1 ■ |
2! |
4! |
v |
2л! |
|
11 |
|
у |
= |
х |
х2 |
х3 |
|
|
|
|
|
е = 1+ — + — |
+ — +...+— +..., х < оо , |
|
|
|
1! |
2 ! |
3! |
л! |
|
|
|
|
у |
= 1п(1 + х) = х - — +...+(-1)”+ |
— +..., |
|х| < 1 , |
|
|
|
|
2 |
|
л |
|
|
|
|
|
|
х3 |
х5 |
x2n+1 |
X <00, |
у = sh(x) = х + — + |
— ------- +..., |
|
|
|
3! |
5! |
(2л+1)! |
|
|
|
|
|
|
г2 |
г4 |
г2п |
|
|
|
|
у = ch(x) s= 1 + — |
+ — +... |
+---- +... |
, |х| < оо. |
, |
' |
2! |
4! |
2л! |
11 |
Глава 10. Задачи по программированию |
499 |
Указанные разложения малоэффективны при больших по модулю значениях аргумента, так как ряды в этих случаях схо дятся медленно.
Рекомендации.
1. Для тригонометрических функций следует автоматически приводить значение аргумента к величине 0<х<Л"/2. В этом слу чае справедлива оценка остаточного члена R„: |/?„|<|м„, ф поэто му счет можно прекращать при \и„\<£.
2. Для показательной функции можно представить значение аргумента в виде х=Е(х)+г, где Е(х) - целая часть х, г - дробная часть (0<г<1). В этом случае е х = е Е(-х ) е г ; еЕ<х>вычисляется как
,"г2
е= г + —+ — +... с остаточным членом |/?„|<|ы„|, что справедливо
для |г|<1, поэтому счет следует вести до \ип\<£, используя в каче стве £ оценку машинного нуля.
Для функции sh(x) остаточный член Rn <-у- для 0<х<п.
Для функции ch(x) остаточный член R„ <—ип при 0<|х|<н.
Таким образом, для функций ch(x), sh(x) при больших значе ниях х рекомендуется вначале получить грубое приближение для п<х, а затем продолжать вычисления до "машинного нуля".
Варианты заданий по итерационным методам и рядам.
Ниже приведена табл. 10.3, содержащая варианты заданий.
Таблица 10.3
Варианты заданий по итерационным методам и рядам
|
№ |
а;Ь |
№ |
№ |
а;Ь |
е~ х 4 х |
1;3 |
|
19 |
ln(jc) |
1;1.5 |
|
3;4 |
|
20 |
l-bln2(jc) |
0.4; 1 |
x - J x |
4;5 |
|
21 |
\+ е* |
0.5; 1 |
500
№
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
f ( x )
1 / ^ 1/V?
( 2 х +1 )/V ?
л/хг + 1
\ [ х ■COSX
&
ег • sinx
л/х ■COSX
sin(x + 0.5)
sin(x2)
sin(x)/x
cos(x)/x2
x + sin(x)
x 1 - cos(x)
Программирование на языке Си
a ; b |
№ |
5;7 |
22 |
|
6;8 |
23 |
|
8;9 |
24 |
|
0.5; 1 |
25 |
|
2.5;3 |
26 |
|
1;1.5 |
27 |
|
3.5;4 |
28 |
|
0;я/4 |
29 |
- |
n /9 ;n /4 |
30 |
|
тг/18;тг/3 |
31 |
|
7t/4;7t/2 |
32 |
|
0.2;0.4 |
33 |
|
7t/16;7t/4 |
34 |
|
0.4;0.6 |
35 |
|
7г/4;7г/2 |
|
|
т
«‘*/2
cos(x)e'r
1/(1+0
sin(x)sh(x)
0.5+sh2(x)
yfx~- ch(x)
l/(l+ch2(x))
■Jx~- sh(x)
e'rch(x)
ln(x2)
x+lnx
l/(l+sinx)
sinx + Vx
x(l-cos)
П р о д о л ж е н и е
a ; b
2;3
1;2
3;4
l;5
2;3
3;4
2;4
i;5
1;4 1; 1.4 1; 5
rt/3; 7t/6 7t/6; 7t/4 0.4; 0.8
Пример выполнения задания. |
|
|
Вычислить табл. |
10.3 из 11 значений заданной |
функции |
f ( x ) - |
4 х -sh(jc) на интервале [а,Ь], |
где а = 1, b = 5. Столбцы |
табл. 10.2 следующие: |
|
|
|
1- |
значение х,; |
|
|
|
2 -значение f t(x), |
вычисленное с |
использованием |
библио |
течных функций и компилятора; |
|
|
3 |
- значение f/x ), вычисленное с помощью явного разло |
жения в ряд или итерационного процесса (до достижения "машинного нуля");
Глава 10. Задачи по программированию |
501 |
4 -значение "машинного нуля" относительно f(x/), т.е. точ ность вычислений;
5 - количество итераций или количество членов ряда в раз ложении функции.
С применением библиотечных функций можно записать:
у = sqrt(jc) * sinh(jc).
Для вычисления приближенного значения у[х воспользуемся формулой Ньютона:
1 х
Уп+\ = ^ ( У п + — ),« = 0 , 1 , . . .
zУп
Вкачестве начального приближения возьмем уо=х. В качест ве условия окончания процесса используем равенство:
У п+l Уп •
Для вычисления гиперболического синуса sh(x) используем ряд Тейлора:
sh(x) = * + — + — +...
Условием окончания вычислений гиперболического синуса пусть будет "неизменность" накопленной суммы после добавле ния очередного члена ряда.
Точность результатов будем оценивать как разность между значением функции, вычисленным с помощью библиотечных функций, и значением, полученным с помощью приведенных формул.
Числом итераций будем считать максимальное из двух зна
чений - |
количество итераций по формуле Ньютона и количест |
во членов, использованных в разложении sh(x) в ряд. |
И с п о л ь з у е м ы е пе ре ме нн ые : |
yt |
- значение у[х ■sh(x), полученное с помощью биб |
|
лиотечных функций; |
502 |
Программирование на языке Си |
ус |
- значение yfx sh(x), вычисленное с помощью явно |
|
го разложения в рядвЦх) и по формуле Ньютона |
|
для у[х ; |
а- точность подсчета;
sq |
- |
текущее |
значение |
приближения при |
вычисле |
|
|
нии у[х ; |
|
|
|
|
sqO |
- |
предыдущее значение приближения для у[х ; |
sh |
- |
текущее значение члена ряда при вычислении функ |
|
|
ции у = sh(jc); |
|
|
|
sum |
- |
сумма ряда, подсчитанная при разложении функции |
|
|
у = sh(jc); |
|
|
|
sm |
- |
предыдущее значение суммы ряда sum; |
|
shn |
- |
счетчик |
элементов |
ряда |
разложения |
функции |
|
|
У = sh(jc); |
|
|
|
sqn |
- |
счетчик |
итераций |
при |
вычислении |
функции |
у- sqrt(x);
х- значения х„ в которых производятся вычисления значений у[х ■sh(x).
П с е в д о к о д пр ог раммы:
Цикл для х от 1 до 5 при изменении х с шагом 0.4. Вычислить y t - "табличное"значение sqrt(x)*sinh(x) в точке х.
Найти значение функцииу= у[х в точке х, т.е. sq. Найти значение функцииy=sh(x) в точке х, т.е. sum. Вычислить для х значение ус = sq*sum.
Оценить точность вычислений. Конец-цикла.
Вывести результаты.
Глава 10. Задачи по программированию |
503 |
Те к ст пр ог рам мы:
/* Вычисление функции: у = sqrt(х)*sinh(х) */ #include <stdlib.h>
#include <math.h> #include <stdio.h> void main()
{
double yt,yc,a,x; |
|
double sq, sqO, sh, sum, sm; |
unsigned long |
sqn,n,shn; |
printf("\n\t Вычисление функции: у =" |
"sqrt(x)*sinh(x)\n\n"); |
printf("x \t |
f1 (x) \t |
f2(x)\t To4HOCTb\t" |
" Итерации\п"); |
x+=0.4) |
for ( x=l.0; |
x <= 5.01; |
{ / * Ц И К Л П О X * / |
|
yt=sqrt(x)*sinh(x); /* Библиотечные функции*/ |
sqn=0; /* Счетчик итераций */
sq=x; /* Начальное приближение для корня */ do
{ /* Цикл вычисления квадратного корня */ sqn++; /* Счетчик итераций */
sqO = sq;
sq = (sqO+х/(sqO))/2;
}
while(sq |
!= sqO); |
shn = 1; /* Счетчик членов ряда */ |
sh = x; /* Значение первого члена ряда */ |
sum = |
0; |
|
n = |
1; |
|
do |
|
|
вычисления гиперболического синуса*/ |
{/ Цикл |
sm=sum; |
sum |
+= |
sh; |
sh |
= |
sh* ((x*x) / ((n+1) * (n+2))) ; |
n |
+= |
2 ; |
shn++; |
/* Номер члена ряда */ |
' } |
|
|
|
while (sm != s\im) ; yc = sq*sum;
/* Точность - сравнение с библиотечными