Міністерство освіти і науки України
Національний університет „ Львівська політехніка ”
Кафедра ЕОМ
Звіт
з лабораторної роботи №1
на тему: „ Аналіз обчислювальної похибки при виконанні базових операцій алгоритмів ЦОСЗ. Обчислення математичних функцій. ”
з курсу : Проектування комп'ютерних засобів обробки сигналів та зображень
Львів
2007
Тема: Аналіз обчислювальної похибки при виконанні базових операцій алгоритмів ЦОСЗ. Обчислення математичних функцій.
Мета: дослідити шляхи виникнення обчислювальної похибки та її вплив на точність обчислень; проаналізувати величину похибки при обчисленні деяких математичних функцій.
Хід роботи
При реалізації обчислень на процесорах обробки сигналів чи НВІС, які характеризуються обмеженою розрядністю і роботою в форматі фіксованої крапки необхідно враховувати ефекти, які викликані, насамперед, наближеним представленням формули обчислень і кінцевою розрядністю використовуваних регістрів. До таких ефектів відносяться:
шум аналогово-цифрового перетворення
некорельований шум заокруглення
похибки, які викликані квантуванням коефіцієнтів
Враховуючи методи представлення чисел, способи квантування, які використовуються для скорочення розрядності чисел до необхідної величини, а також особливості структурної схеми обчислень, в кожному конкретному випадку можна оцінити, як перераховані ефекти впливають на результат обчислень.
Квантування в цифрових пристроях.
При квантуванні використовують два стандартних способи: відкидання і заокруглення. Розглянемо їх особливості стосовно різних систем числення і похибки, які виникають при цьому. Припускається, що всі значення чисел по модулю менші від 1.0 (|X| < 1.0).
Відкидання. Відкидуються всі молодші розряди, що стоять після найменшого розряду, який зберігається. Тоді значення похибки для додаткового коду задовільняє нерівність:
-2 -b ( Xвдк - X ( 0,
де b - число розрядів, що зберігаються; Xвдк - відкинуте значення X.
Для чисел, які представлені в прямому і оберненому кодах для від’ємних значень справедлива нерівність:
0 ( Xвдк - X < 2-b , X < 0.
Hайважливіше, що похибка відкидання лежить між значеннями нуля і числа, що пропорційне (2-b .
Заокруглення. При заокругленні вихідне число X заміняється найближчим до нього b-розрядним числом. Тоді похибка заокруглення задовільняє нерівність:
-2-b / 2 ( Xок - X ( 2-b / 2
для всіх трьох методів представлення чисел (додаткового, прямого і оберненого коду).
Шум аналогово-цифрового перетворення.
В залежності від методу квантування вхідної послідовності шум квантування може мати різний амплітудний розподіл.
При найменшому кроці квантування Q похибка квантування e(n) лежить в границях:
-Q/2 ( e(n) ( Q/2 - для випадку заокруглення;
0 ( e(n) ( Q - для випадку відкидання;
а розподіл сигналу похибки є рівномірним. При цьому середнє значення похибки дорівнюватиме нулю при заокругленні і Q/2 при відкиданні, а її дисперсія в обидвох випадках дорівнюватиме Q 2/12. Як аналогію аналогово-цифрового перетворення в нашому випадку необхідно розглядати представлення вхідного (тестового) масиву чисел в заданій розрядній сітці b, тоді Q дорівнюватиме b.
Hекорельований шум заокруглення.
В цифровій обробці використовуються операції множення, додавання і зсуву. Їх виконання приводить до необхідності розширення розрядної сітки. Hаприклад, перемноження двох b-розрядних чисел приводить до 2b-розрядного результату, подальше перемноження може привести до безкінцевого збільшення розрядної сітки. Для подолання ефекту застосовують квантування результатів множення до вихідної b-розрядної сітки з заокругленням або відкиданням молодших розрядів. При цьому виникає шум заокруглення.
При додаванні в загальному випадку розширення розрядної сітки не виникає, але в деяких випадках може виникнути переповнення. Для подолання цього ефекту застосовують зсув результатів вправо і його квантування. Для квантування результатів множення і додавання застосовують заокруглення або відкидання, в залежності від вимог реалізації. Похибки, що виникають при цьому будуть мати випадковий характер.
Квантування коефіцієнтів.
Постійні коефіцієнти, які використовуються при обчисленні базових операцій алгоритмів ЦОСЗ також представляються у фіксованому розрядному просторі. Загального підходу до їх квантування нема, тому застосовується така оптимизація, щоб максимум взваженої різниці ідеальних і реальних обчисленнь був мінімальним. При цьому необхідно розглянути схему обчисленнь стосовно чутливості до розрядності коефіцієнтів. Для цього, необхідно, змінюючи спосіб квантування коефіцієнтів (відкидання, заокруглення), добитися найменшого розходження між ідеальною і розрахованою функцією.
Завдання:
sin x
(| x | ( ()
x ( ]0., (/2[
(x = 0.02
Блок схема виконання алгоритму:
Вихідний код програми, написаної з використанням фреймворку Adobe Flex 2:
PKZOSZ.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
width="640" height="480" creationComplete="proccess();">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import lab1.SinFx;
[Embed(source="assets/COPRGTB.TTF", fontName="Modern", mimeType="application/x-font")]
private var font1:Class;
public var resDataProvider:ArrayCollection;
private function proccess():void {
//process emulation
var testFX:SinFx = new SinFx(0.02);
testFX.processEmulation();
resDataProvider = testFX.emulResult;
//set data providers
generalTable.dataProvider = resDataProvider;
}
]]>
</mx:Script>
<mx:ToggleButtonBar x="0" y="0" width="640" height="25" dataProvider="Views"/>
<mx:ViewStack id="Views" width="630" height="445" borderStyle="solid"
horizontalCenter="0" verticalCenter="12.5">
<mx:VBox label="General table" width="100%" height="100%"
verticalAlign="top" horizontalAlign="left">
<mx:DataGrid id="generalTable" width="100%" height="60%" resizableColumns="false">
<mx:columns>
<mx:DataGridColumn headerText="x" dataField="x" width="37"/>
<mx:DataGridColumn headerText="Fx" dataField="y"/>
<mx:DataGridColumn headerText="8bit" dataField="y_8bit"/>
<mx:DataGridColumn headerText="16bit" dataField="y_16bit"/>
<mx:DataGridColumn headerText="AbsErr 8bit" dataField="absErr_8bit"/>
<mx:DataGridColumn headerText="AbsErr 16bit" dataField="absErr_16bit"/>
<mx:DataGridColumn headerText="RelErr 8bit Fx" dataField="relErr_8bit"/>
<mx:DataGridColumn headerText="RelErr 16bit Fx" dataField="relErr_16bit"/>
</mx:columns>
</mx:DataGrid>
<mx:VBox verticalGap="0">
<mx:HBox horizontalGap="5">
<mx:Label fontFamily="Modern" fontSize="13" text="Argument: " width="140" textAlign="right"/>
<mx:Label fontFamily="Verdana" fontSize="12" text="{generalTable.selectedItem.x}"/>
</mx:HBox>
<mx:HBox horizontalGap="5">
<mx:Label fontFamily="Modern" fontSize="13" text="Fx: " width="140" textAlign="right"/>
<mx:Label fontFamily="Verdana" fontSize="12" text="{generalTable.selectedItem.y}"/>
</mx:HBox>
<mx:HBox horizontalGap="5">
<mx:Label fontFamily="Modern" fontSize="13" text="Fx 8bit: " width="140" textAlign="right"/>
<mx:Label fontFamily="Verdana" fontSize="12" text="{generalTable.selectedItem.y_8bit}"/>
</mx:HBox>
<mx:HBox horizontalGap="5">
<mx:Label fontFamily="Modern" fontSize="13" text="AbsErr 8bit Fx: " width="140" textAlign="right"/>
<mx:Label fontFamily="Verdana" fontSize="12" text="{generalTable.selectedItem.absErr_8bit}"/>
</mx:HBox>
<mx:HBox horizontalGap="5">
<mx:Label fontFamily="Modern" fontSize="13" text="RelErr 8bit Fx: " width="140" textAlign="right"/>
<mx:Label fontFamily="Verdana" fontSize="12" text="{generalTable.selectedItem.relErr_8bit}"/>
</mx:HBox>
<mx:HBox horizontalGap="5">
<mx:Label fontFamily="Modern" fontSize="13" text="Fx 16bit: " width="140" textAlign="right"/>
<mx:Label fontFamily="Verdana" fontSize="12" text="{generalTable.selectedItem.y_16bit}"/>
</mx:HBox>
<mx:HBox horizontalGap="5">
<mx:Label fontFamily="Modern" fontSize="13" text="AbsErr 16bit Fx: " width="140" textAlign="right"/>
<mx:Label fontFamily="Verdana" fontSize="12" text="{generalTable.selectedItem.absErr_16bit}"/>
</mx:HBox>
<mx:HBox horizontalGap="5">
<mx:Label fontFamily="Modern" fontSize="13" text="RelErr 16bit Fx: " width="140" textAlign="right"/>
<mx:Label fontFamily="Verdana" fontSize="12" text="{generalTable.selectedItem.relErr_16bit}"/>
</mx:HBox>
</mx:VBox>
</mx:VBox>
<mx:Box label="Plot of functions" width="100%" height="100%"
verticalAlign="top" horizontalAlign="center">
<mx:Legend verticalGap="2" dataProvider="{chartFX}" direction="horizontal"/>
<mx:Box height="330" width="620" maxWidth="620">
<mx:LineChart id="chartFX" showDataTips="true" width="620" height="300"
dataProvider="{resDataProvider}">
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="x"/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries id="lineFx" displayName="Fx" yField="y"/>
<mx:LineSeries id="lineFx8bit" displayName="8bitFx" yField="y_8bit"/>
<mx:LineSeries id="lineFx16bit" displayName="16bitFx" yField="y_16bit"/>
</mx:series>
</mx:LineChart>
</mx:Box>
<mx:Box>
<mx:HBox>
<mx:Label text="Scale-X options: "/>
<mx:Button label="Down" width="50" height="15"
click="{chartFX.width == 620 ? chartFX.width:chartFX.width -= 100}"/>
<mx:Button label="Up" width="50" height="15"
click="{chartFX.width > 4000 ? chartFX.width:chartFX.width += 100}"/>
<mx:Button label="Reset" width="50" height="15" click="{chartFX.width = 620}"/>
</mx:HBox>
<mx:HBox>
<mx:Label text="Draw options: "/>
<mx:CheckBox label="Draw Fx chart" selected="true"
click="{lineFx.visible = !lineFx.visible}"/>
<mx:CheckBox label="Draw 8bitFx chart" selected="true"
click="{lineFx8bit.visible = !lineFx8bit.visible}"/>
<mx:CheckBox label="Draw 16bitFx chart" selected="true"
click="{lineFx16bit.visible = !lineFx16bit.visible}"/>
</mx:HBox>
</mx:Box>
</mx:Box>
<mx:Box label="Plot of absolute errors" width="100%" height="100%"
verticalAlign="top" horizontalAlign="center">
<mx:Legend verticalGap="2" dataProvider="{chartAbsErr}" direction="horizontal"/>
<mx:Box height="330" width="620" maxWidth="620">
<mx:LineChart id="chartAbsErr" showDataTips="true" width="620" height="300"
dataProvider="{resDataProvider}">
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="x"/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries id="lineAbsErrFx8bit" displayName="AbsErr8bitFx" yField="absErr_8bit"/>
<mx:LineSeries id="lineAbsErrFx16bit" displayName="AbsErr16bitFx" yField="absErr_16bit"/>
</mx:series>
</mx:LineChart>
</mx:Box>
<mx:Box>
<mx:HBox>
<mx:Label text="Scale-X options: "/>
<mx:Button label="Down" width="50" height="15"
click="{chartAbsErr.width == 620 ? chartAbsErr.width:chartAbsErr.width -= 100}"/>
<mx:Button label="Up" width="50" height="15"
click="{chartAbsErr.width > 4000 ? chartAbsErr.width:chartAbsErr.width += 100}"/>
<mx:Button label="Reset" width="50" height="15" click="{chartAbsErr.width = 620}"/>
</mx:HBox>
<mx:HBox>
<mx:Label text="Draw options: "/>
<mx:CheckBox label="Draw AbsErr8bitFx chart" selected="true"
click="{lineAbsErrFx8bit.visible = !lineAbsErrFx8bit.visible}"/>
<mx:CheckBox label="Draw AbsErr16bitFx chart" selected="true"
click="{lineAbsErrFx16bit.visible = !lineAbsErrFx16bit.visible}"/>
</mx:HBox>
</mx:Box>
</mx:Box>
<mx:Box label="Plot of relative errors" width="100%" height="100%"
verticalAlign="top" horizontalAlign="center">
<mx:Legend verticalGap="2" dataProvider="{chartRelErr}" direction="horizontal"/>
<mx:Box height="330" width="620" maxWidth="620">
<mx:LineChart id="chartRelErr" showDataTips="true" width="620" height="300"
dataProvider="{resDataProvider}">
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="x"/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries id="lineRelErrFx8bit" displayName="RelErr8bitFx" yField="relErr_8bit"/>
<mx:LineSeries id="lineRelErrFx16bit" displayName="RelErr16bitFx" yField="relErr_16bit"/>
</mx:series>
</mx:LineChart>
</mx:Box>
<mx:Box>
<mx:HBox>
<mx:Label text="Scale-X options: "/>
<mx:Button label="Down" width="50" height="15"
click="{chartRelErr.width == 620 ? chartRelErr.width:chartRelErr.width -= 100}"/>
<mx:Button label="Up" width="50" height="15"
click="{chartRelErr.width > 4000 ? chartRelErr.width:chartRelErr.width += 100}"/>
<mx:Button label="Reset" width="50" height="15" click="{chartRelErr.width = 620}"/>
</mx:HBox>
<mx:HBox>
<mx:Label text="Draw options: "/>
<mx:CheckBox label="Draw RelErr8bitFx chart" selected="true"
click="{lineRelErrFx8bit.visible = !lineRelErrFx8bit.visible}"/>
<mx:CheckBox label="Draw RelErr16bitFx chart" selected="true"
click="{lineRelErrFx16bit.visible = !lineRelErrFx16bit.visible}"/>
</mx:HBox>
</mx:Box>
</mx:Box>
</mx:ViewStack>
</mx:Application>
SinFx.as
package lab1 {
import mx.collections.ArrayCollection;
public class SinFx {
private var deltaX:Number = 0;
private var result:ArrayCollection = new ArrayCollection();
private var factor8bit:Number;
private var factor16bit:Number;
/*
* Constructor.
*/
public function SinFx (deltaX:Number) {
this.deltaX = deltaX;
//calc convert factor, 1 bit for float flag
this.factor8bit = 128/Math.pow(Math.PI/2, 2*3-1);
this.factor16bit = 327768/Math.pow(Math.PI/2, 2*4-1);
}
/*
* Getter for private var result
*/
public function get emulResult():ArrayCollection {
return this.result;
}
/*
* Calculate Fx value using series and 8bit precision.
*/
private function calcSequen8bValue(x:Number):Number {
var tmpRes:Number = 0;
//use 3 elements of sequence
for(var n:uint = 1; n<=3; n++) {
tmpRes += Math.pow(-1, n-1) * apply8bit((apply8bit(Math.pow(x, 2*n-1)) / factorial(2*n-1)));
}
return tmpRes;
}
/*
* Calculate Fx value using series and 16bit precision.
*/
private function calcSequen16bValue(x:Number):Number {
var tmpRes:Number = 0;
//use 4 elements of sequence
for(var n:uint = 1; n<=4; n++) {
tmpRes += Math.pow(-1, n-1) * apply16bit((apply8bit(Math.pow(x, 2*n-1)) / factorial(2*n-1)));
}
return tmpRes;
}
/*
* Convert number to number with 8bit precision.
*/
private function apply8bit(x:Number):Number {
return ((parseInt((x * factor8bit).toFixed(0)))&0xFF)/factor8bit;
}
/*
* Convert number to number with 16bit precision.
*/
private function apply16bit(x:Number):Number {
return ((parseInt((x * factor16bit).toFixed(0)))&0xFFFF)/factor16bit;
}
/*
* Computes and returns an factorial value
* for the number specified by the parameter.
*/
private function factorial(x:uint):uint {
return (x > 1) ? x * factorial(x - 1) : 1;
}
/*
* Main method, that calculate Fx values in different
* calculating modes.
*/
public function processEmulation():void {
var curAnalytValue:Number = 0;
var curSequenValue_8bit:Number = 0;
var curAbsErr_8bit:Number = 0;
var curRelErr_8bit:Number = 0;
var curSequenValue_16bit:Number = 0;
var curAbsErr_16bit:Number = 0;
var curRelErr_16bit:Number = 0;
var upBound:Number = parseFloat((Math.PI/2).toFixed(2));
for(var x:Number = 0; x <= upBound; x += this.deltaX) {
//fix problem with precision
x = parseFloat(x.toFixed(2));
curAnalytValue = Math.sin(x);
curSequenValue_8bit = calcSequen8bValue(x);
curSequenValue_16bit = calcSequen16bValue(x);
curAbsErr_8bit = Math.abs(curAnalytValue - curSequenValue_8bit);
curAbsErr_16bit = Math.abs(curAnalytValue - curSequenValue_16bit);
curRelErr_8bit = (curAbsErr_8bit / curAnalytValue) * 100;
curRelErr_16bit = (curAbsErr_16bit / curAnalytValue) * 100;
curRelErr_8bit = isNaN(curRelErr_8bit) ? 0 : curRelErr_8bit;
curRelErr_16bit = isNaN(curRelErr_16bit) ? 0 : curRelErr_16bit;
result.addItem({ x: x, y: curAnalytValue, y_8bit: curSequenValue_8bit, y_16bit: curSequenValue_16bit,
absErr_8bit: curAbsErr_8bit, absErr_16bit: curAbsErr_16bit,
relErr_8bit: curRelErr_8bit, relErr_16bit: curRelErr_16bit});
}
}
}
}
Результати виконання лабораторної роботи:
Рис.1. Графік абсолютної похибки 16 розрядних обчислень.
Рис.2. Графік абсолютної похибки 8 розрядних обчислень.
Рис.3. Графік відносної похибки 16 розрядних обчислень.
Рис.4. Графік відносної похибки 8 розрядних обчислень.
Висновок: у ході цієї лабораторної роботи, я дослідив шляхи виникнення обчислювальної похибки та її вплив на точність обчислень; проаналізував величину похибки при обчисленні деяких математичних функцій.