Міністерство освіти і науки України
Національний університет „Львівська політехніка”
Кафедра ЕОМ
Звіт
з лабораторної роботи № 1
з дисципліни:
“Проектування комп'ютерних засобів обробки сигналів і зображень”
на тему:
Аналіз обчислювальної похибки при виконанні базових операцій алгоритмів цифрової обробки сигналів. Обчислення математичних виразів
Мета
Дослідити шляхи виникнення обчислювальної похибки та її вплив на точність обчислень. Проаналізувати величину похибки при обчисленні деяких математичних виразів.
Завдання
Вар.
Функція
Формула розкладу
Додаткові дані
16
ln (3x/4+8)
(3x/4+8 > 0)
x ( ]2.,12[
(x = 0.1
Згідно поставленого завдання, аналітичний вид математичної функцій, що буде обчислюватися, буде мати вигляд( для наочності обчислень беремо 5 членів ряду):
=−(
х
1
1
+
х
2
2
+
х
3
3
+
х
4
4
+
х
5
5
)
Обчисливши коефіцієнти при степенях, отримаємо:
=−(
х
1
1
+
х
2
2
+
х
3
3
+
х
4
4
+
х
5
5
)
Теоретичні відомості
При реалізації обчислень на процесорах обробки сигналів чи НВІС, які характеризуються обмеженою розрядністю і роботою в форматі фіксованої крапки необхідно враховувати ефекти, які викликані, насамперед, наближеним представленням формули обчислень і кінцевою розрядністю використовуваних регістрів. До таких ефектів відносяться:
а) шум аналогово-цифрового перетворення;
б) некорельований шум заокруглення;
в) похибки, які викликані квантуванням коефіцієнтів.
Враховуючи методи представлення чисел, способи квантування, які використовуються для скорочення розрядності чисел до необхідної величини, а також особливості структурної схеми обчислень, в кожному конкретному випадку можна оцінити, як перераховані ефекти впливають на результат обчислень.
Квантування в цифрових пристроях
При квантуванні використовують два стандартних способи: відкидання і заокруглення. Розглянемо їх особливості стосовно різних систем числення і похибки, які виникають при цьому. Припускається, що всі значення чисел по модулю менші від 1.0 (|X| < 1.0).
Відкидання. Відкидаються всі молодші розряди, що стоять після найменшого розряду, який зберігається. Тоді значення похибки для доповняльного коду задовольняє нерівність:
-2 -b ( Xвдк - X ( 0,
де b - число розрядів, що зберігаються; Xвдк - відкинуте значення X.
Для чисел, які представлені в прямому і оберненому кодах для від’ємних значень справедлива нерівність:
0 ( Xвдк - X < 2-b , X < 0.
Важливим є те, що похибка відкидання лежить між значеннями нуля і числа, що пропорційне (2-b .
Заокруглення. При заокругленні вихідне число X заміняється найближчим до нього b-розрядним числом. Тоді похибка заокруглення задовольняє нерівність:
-2-b / 2 ( Xок - X ( 2-b / 2
для всіх трьох методів представлення чисел (додаткового, прямого і оберненого коду).
Блок схема алгоритму, для режиму з фіксованою крапкою наведено на рис. 1.
/
Рис. 1. Блок схема алгоритму, для режиму з фіксованою крапкою
Лістинг
//---------------------------------------------------------------------------
#include "StdAfx.h"
#include <vcl.h>
#pragma hdrstop
#include <math.h>
#include <conio.h>
#include <stdio.h>
double fixed(double fin,int intRank,int rank,bool test);//ПРОТОТИП.
//FIN-ВХІДНЕ ЧИСЛО RANK-РОЗРЯДНІСТЬ ПІСЛЯ КОМИ INTrANK-РОЗРЯДНІСТЬ ЦІЛОЇ ЧАСТИНИ TEST-ВИВІД [FIN_2]
double fixed(double fin,int intRank,int rank,bool test=0)//ФУНКЦІЯ ПЕРЕТВОРЕННЯ У ФІКСОВАНИЙ ФОРМАТ
{
//--IN BINARY-------------------------------------------------------------------------------
double fix=0;//НАША МАЙБУТНЯ ЗМІННА З ФІКСОВАНОЮ КОМОЮ
int i;//ЛІЧИЛЬНИК-РІЗНОРОБОЧИЙ
//--ЦІЛА ЧАСТИНА----------------------------------------------------------------------------
int r=1;//ВАГА РОЗРЯДУ [1.0_2 = 1.0_10]
int xp16[16];//ДЛЯ БІНАРНОГО КОДУ ЦІЛОЇ ЧАСТИНИ
int fint=abs((int)fin);//БЕРЕМО ЛИШЕ ЦІЛУ ЧАСТИНУ
for(i=0;i<16;i++)//ОНУЛЕННЯ БІНАРНИХ РОЗРЯДІВ
xp16[i]=0;
for(i=0 ; fint>0, i<16 ; i++)//ПОКИ ЧИСЛО ДІЛИТЬСЯ НА 2
{
xp16[i]=(int)(fint-((int)(fint/2))*2);//ОСТАЧА ВІД ДІЛЕННЯ НА 2
fint /= 2;//ЦІЛОЧИСЛОВЕ ДІЛЕННЯ НА 2
}
for(i=0;i<intRank;i++)//ЗАЗНАЧЕНА РОЗРЯДНІСТЬ
{
fix=fix + xp16[i] * r;//ЗБИРАННЯ ЦІЛОЇ ЧАСТИНИ
r *= 2;//ЗБІЛЬШЕННЯ ВАГИ РОЗРЯДУ
}
//--ДРОБОВА ЧАСТИНА------------------------------------------------------------------------
double d=0.5;//СТЕПІНЬ ДЛЯ СКЛАДАННЯ ЧИСЛА [0.1_2=0.5_10]
int px16[16];//БУДЕ ЗБЕРІГАТИ КОЖЕН РОЗРЯД БІНАРНОГО КОДУ ДРОБОВОЇ ЧАСТИНИ
double fdot=fin;//КОПІЯ ВХІДНОГО ЧИСЛА
for(i=0;i<16;i++)//ОНУЛЕННЯ БІНАРНИХ РОЗРЯДІВ
px16[i]=0;
if(fin<0)//ЧИСЛО ПО МОДУЛЮ
fdot=-fin;
for(i=0;i<rank;i++)//ЗАЗНАЧЕНА РОЗРЯДНІСТЬ
{
fdot=fdot-(int)fdot;//ВІДОКРЕМЛЕННЯ ЦІЛОЇ ЧАСТИНИ
fdot *= 2;//МНОЖЕННЯ НА 2
px16[i]=(int)fdot;//ЗАПИС У БІНАРНИЙ КОД ЦІЛОЇ ЧАСТИНИ
}
for(i=0;i<rank;i++)//ЗАЗНАЧЕНА РОЗРЯДНІСТЬ
{
if(px16[i]!=0)
fix=fix + px16[i] * d; //ЗБИРАННЯ ЧИСЛА
d *= 0.5;//СТЕПІНЬ ДВІЙКИ ПІСЛЯ КОМИ ЗБІЛЬШУЄТЬСЯ
}
//--RETURN----------------------------------------------------------------------------------
if(test)
{
printf("\n%f = ",fix);
if(fin<0)
printf("[1.");
else
printf("[0.");
for(i=intRank-1; i>=0;i--)
printf("%d",xp16[i]);
printf(".");
for(i=0; i<rank;i++)
printf("%d",px16[i]);
printf("]");
}
if(fin<0)//ВСТАНОВЛЮЄМО ЗНАК
fix=-fix;
return fix;//ВЕРТАЄМО ФІКСОВАНИЙ ФОРМАТ
}
int main()
{
//------відкриття файлу--------------------
FILE* filePointer;
char file_name[32] = "Resalts.txt";
filePointer = fopen(file_name,"wt");
// double s_abs8=0,s_abs16=0;
// double max_abs8=0,max_abs16=0;
printf("-------------------------------------------------------------------------------\n");
printf(" x | fe | f16 | f8 | %c 16 | %c 8 | %c 16 | %c 8\n"
,(char)127,(char)127,(char)243,(char)243);
printf("------+---------+------------------+---------+---------+--------+------+-------\n");
//------РОЗРАХУНОК Ф-Ї ЧЕРЕЗ DOUBLE---------
double x;
bool zero=false;
bool ones=false;
for(x=-1.0 ; x<1.0 ; x=x+0.05) //прописуємо крок і межі
{
double f=0;
double f8=0,f16=0;
int n;
for(n=1;n<5;n++)
{
f=-f+pow(x,n)/n;
int r1=4,r2=3;
double const_n = fixed(n,r1,r2);
double const_x = fixed(x,r1,r2);
double const_2 = fixed(2,r1,r2);
double const_1 = fixed(1,r1,r2);
double const_2n = fixed(const_2 * const_n,r1,r2);
double const_2n_p1 = fixed(const_2n + const_1,r1,r2);
double x_pow = fixed(pow(const_x,const_2n_p1),r1,r2);
f8=f8+ fixed(x_pow/const_2n_p1,r1,r2);
r1=4,r2=11;
const_n = fixed(n,r1,r2);
const_x = fixed(x,r1,r2);
const_2 = fixed(2,r1,r2);
const_1 = fixed(1,r1,r2);
const_2n = fixed(const_2 * const_n,r1,r2);
const_2n_p1 = fixed(const_2n + const_1,r1,r2);
x_pow = fixed(pow(const_x,const_2n_p1),r1,r2);
f16=f16+ fixed(x_pow/const_2n_p1,r1,r2);
}
if(!(((int)(x*1000))!=0))
zero=true;
//------ABSOLUTNA POXUBKA--------------------
double abs16=f-f16;
if(abs16 < 0)
abs16 = -abs16;
double abs8=f-f8;
if(abs8 < 0)
abs8 = -abs8;
//------VIDNOSNA POXUBKA----------------------
double vid16;
if(f16 != 0)
vid16=(abs16/f)*100;
else
vid16=0;
double vid8;
if(f8 != 0)
vid8=(abs8/f)*100;
else
vid8=0;
//------OUTPUT-------------------------------
if(x>=0)
printf(" ");
printf("%.3f|%f|%.15f|%f|%.7f|%f|%2.3f|%2.3f\n"
,x,f,f16,f8,abs16,abs8,vid16,vid8);
/*
s_abs8+=abs8;
s_abs16+=abs16;
if(max_abs8<abs8)
max_abs8+=abs8;
if(max_abs16<abs16)
max_abs16+=abs16;
*/
fprintf(filePointer,"%.2f %f %.15f %f %.7f %f %2.3f %2.3f\n"
,x,f,f16,f8,abs16,abs8,vid16,vid8);
if(zero && ones)
{
getch();
ones=false;
}
}
fclose(filePointer);
// printf("\n, %f %f",s_abs16/100,max_abs16);
getch();
return 0;
}
Результат виконання
/
Рис.1. Результати роботи програми.
Висновок
Виконавши дану лабораторну роботу, я дослідив шляхи виникнення обчислювальної похибки та її вплив на точність обчислень, проаналізував величину похибки при обчисленні деяких математичних виразів.