Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Архитектура учебник (book.pdf)

.pdf
Скачиваний:
19
Добавлен:
24.05.2015
Размер:
405.05 Кб
Скачать

r=3 2(1−t)2+3t2 (1−t )P2 +t3 .

Знаем, что длина вектора тем больше, чем больше производная функции, задающей ее.

Найдем производную данной функции:

r '=3 2(1−t)2−6 2(1−t )+6 P2 t (1−t)−3 P2 t2+3t2=(9 2−9 P2+3)t2−(122−6 P2 )t+3 2 .

Найдем корни квадратного уравнения.

t1,2=

6

2

−3±

27−45

2

+27

2

P2

 

 

.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

92−9 P2+3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Проанализировав

производную

 

можно

понять,

что максимальное значение

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6 2−3−27−45

2+27

 

P2

 

 

 

 

 

 

длины вектора

r будет при

t1

=

2

, а минимальное

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

9 2−9 P2+3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6

 

−3+

 

 

 

 

 

 

 

 

 

значение

длины

вектора будет

при

t2 =

2

27−45

2

+27

2

P2

 

 

. Найдем

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

9 2−9 P2 +3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

t1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

отношение

 

, и, учитывая, что длина вектора

 

r прямо пропорциональна

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

t2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

t3

, получим формулу:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

t1

 

6

 

 

 

−3−

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

27−45

2

+27

2

P2

3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

=

 

 

 

 

 

 

 

 

 

=k .

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

t2

6

 

−3+

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

27−45

 

+27

 

P2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

2

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Найдем

P2

такое, что k=300.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Подставим в формулу k=300 и получаем, что длина вектора P2≈2102.

 

Подберем такие значения x и y, чтобы длина вектора была равна 2102.

Пусть x=2100, y=2.5.

Проверим работоспособность программы при новых начальных условиях (Рисунок 9).

11

Рисунок 9: Относительная погрешность работы в "критических условиях"

Как видим, при новых начальных условиях «скачки» начали проявляться при малых N. Нас это не устраивает. Попробуем решить эту проблему.

Гипотеза №3.

Очевидно, что погрешность суммирования при вычислении длины L все также накапливается. Но избавится от нее путем замены одной арифметической операции на другую (как сделали в Листинге 4) не получится, так как длина каждого последующего полученного вектора, в любом случае, должна суммироваться с предыдущими результатами.

Математическое обоснование:

Вместо Lожид=(((L+dL)+dL)+dL+...+dL) ,

получаем, Lитог=((((L+dL)(1±e )+dL)(1±e)+dL)+...+dL)(1±e) .

Возможное решение:

Попробуем реализовать алгоритм Кэхэна (Листинг 5).

Википедия: «В вычислительной математике алгоритм Кэхэна — это алгоритм вычисления суммы последовательности чисел с плавающей запятой, который значительно уменьшает вычислительную погрешность по сравнению с наивным подходом. Уменьшение погрешности достигается введением

12

дополнительной переменной для хранения нарастающей суммы погрешностей» [2].

Листинг 5. Реализация функции нахождения длины с использованием алгорима Кэхэна.

/* функция вычисления длины кривой по координатам x,y */

float Dlina (int N,float x0,float y0,float x1,float y1,float x2,float y2,float x3,float y3) { float t,X,Y,x,y,l,L=0,pogr=0,true_l=0,TrueL=0; /* введение доп.переменных */ int i=1;

x=F(x0,x1,x2,x3,0); /* вычисление координат первого вектора */ y=F(y0,y1,y2,y3,0);

X=F(x0,x1,x2,x3,1.0/N);

Y=F(y0,y1,y2,y3,1.0/N); for (;t<1 && i<N;i++) {

true_l=Dl(X,x,Y,y)-pogr;

TrueL=L+true_l; /* L велика, true_l мало, так что младшие разряды true_l потеряны */ pogr=TrueL-L-true_l; /*восстановление разрядов pogr */

L=TrueL;

t=((float)i)/N; /* изменение переменной t */ x=F(x0,x1,x2,x3,t);

y=F(y0,y1,y2,y3,t); l=((float)(i+1))/N; X=F(x0,x1,x2,x3,l); Y=F(y0,y1,y2,y3,l);

true_l=Dl(X,x,Y,y)-pogr; L+=true_l;

return L;

}

Оценим результат внесенных изменений для N=1000..5000 при начальных условиях (Рисунок 10).

Относительная погрешность

0,00E+000

 

 

 

 

 

 

 

 

 

100

600

1100

1600

2100

2600

3100

3600

4100

4600

-5,00E-006

 

 

 

 

 

 

 

 

 

-1,00E-005

 

 

 

 

 

 

 

 

 

-1,50E-005

 

 

 

 

 

 

 

 

 

-2,00E-005

 

 

 

 

 

 

 

 

 

-2,50E-005

 

 

 

 

 

 

 

 

 

-3,00E-005

 

 

 

 

 

 

 

 

 

-3,50E-005

 

 

 

 

 

 

 

 

 

-4,00E-005

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Число шагов

Рисунок 10: Результат работ программы с алгоритмом Кэхэна

при начальных условиях.

13

 

Как видим из графика результат работы программы с реализацией алгоритма Кэхэна (Рисунок 10 ) для Листинга 5, «скачки» исчезли.

Теперь посмотрим результат работы программы с реализацией алгоритма Кэхэна в критических условиях при N=1000..5000 (Рисунок 11).

погрешность

0

 

 

 

 

 

 

 

 

 

10

20

30

40

50

60

70

80

90

100

0

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

 

 

Относительная

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Число шагов

 

 

Рисунок 11: График работы программы в критических условиях

Как можно заметить, «скачки» при работе прог ≈−1,5 10−6 раммы исчезли. Реализация алгоритма Кэхэна значительно улучшила результаты работы программы (Рисунок 9 и 11). Построим графики для Листинга 4 и Листинга 5 в одной области для их сравнения и анализа.

Рисунок 12: Листинг 4 и 5. N=1..10000

Рисунок 13: Листинг 4 и 5. N=1000..10000

Из Рисунок 12 можно заметить, что при N ~ 1..500 графики Листинга 4 и Листинга 5 совпадают. Это означает, что при малом числе шагов реализация алгоритм Кэхэна незначительно повлияла на погрешность вычислений, что же происходит при больших N?

Рассмотрим график относительной погрешности для листингов 4 и 5 для N=1000..10000 (Рисунок 13). Как видим, для больших N алгоритм Кэхэна существенно влияет на вычисление длины. Можно заметить, что при реализации функции вычисления длины кривой без алгоритма Кэхэна наблюдаются большое количество «скачков» в графике относительной погрешности (как в положительную, так и в отрицательную сторону). При реализации же данного алгоритма мы получаем плавно изменяющийся график относительной погрешности, причем ЕЛистинг 5→0 , а также ЕЛистинг 4 ЕЛистинг 5 .

Это означает, что высказанная гипотеза верна. Реализация алгоритма Кэхэна в функции вычисления длины значительно улучшила программу, уменьшив погрешность вычислений.

15

Листинг 6. Итоговая программа.

#include <stdio.h> #include <math.h>

#define reference 2.48112398487 /* эталонное решение */

/* функция вычисления относительной погрешности */ float E (float rez) {

return (rez-reference)/(reference);

}

/* функция вычисления координат */

float F (float a0,float a1,float a2,float a3,float t) { float a;

a=pow((1-t),3)*a0+3*t*pow((1-t),2)*a1+3*t*t*(1-t)*a2+pow(t,3)*a3; return a;

}

/* функция вычисления длины через модуль разности векторов */ float Dl (float X, float x, float Y, float y) {

return (sqrt(pow((X-x),2)+pow((Y-y),2)));

}

/* функция вычисления длины кривой по координатам x,y */

float Dlina (int N,float x0,float y0,float x1,float y1,float x2,float y2,float x3,float y3) { float t,X,Y,x,y,l,L=0,pogr=0,true_l=0,TrueL=0;

int i=1; x=F(x0,x1,x2,x3,0); y=F(y0,y1,y2,y3,0); X=F(x0,x1,x2,x3,1.0/N); Y=F(y0,y1,y2,y3,1.0/N); for (;t<1 && i<N;i++) {

true_l=Dl(X,x,Y,y)-pogr; TrueL=L+true_l; pogr=TrueL-L-true_l; L=TrueL;

t=((float)i)/N; x=F(x0,x1,x2,x3,t); y=F(y0,y1,y2,y3,t); l=((float)(i+1))/N; X=F(x0,x1,x2,x3,l); Y=F(y0,y1,y2,y3,l);

}

true_l=Dl(X,x,Y,y)-pogr; L+=true_l;

return L;

}

void main () {

float x0,y0,x1,y1,x2,y2,x3,y3,L,pogr; int N;

scanf("%f%f",&x0,&y0); /* считывание координат */ scanf("%f%f",&x1,&y1); /* считывание координат */ scanf("%f%f",&x2,&y2); /* считывание координат */ scanf("%f%f",&x3,&y3); /* считывание координат */ printf("Число шагов;Погрешность\n");

for (N=1000;N<5001;N++) { /* цикл для количества разбиений (1..100) */

L=Dlina(N,x0,y0,x1,y1,x2,y2,x3,y3); pogr=E(L); printf("%5d;%20.10f\n", N,pogr);

}

}

16

Список литературы.

[1]IEEE 754 — Стандарт двоичной арифметики с плавающей точкой [электронный ресурс] .- Доступ к ресурсу: http://www.softelectro.ru/ieee754.html .

[2]Алгоритм Кэхэна [электронный ресурс] .- Доступ к ресурсу:

https://ru.wikipedia.org/wiki/Алгоритм_Кэхэна .

17