3573

Алгоритми роботи з дійсними числами

Лекция

Информатика, кибернетика и программирование

Дійсні числа представляються в комп'ютері в так названої експонентної, або плаваючої, форми. Дійсне число r має вигляд

Украинкский

2012-11-03

89.5 KB

4 чел.

Алгоритми роботи з дійсними числами

Дійсні числа представляються в комп'ютері в так названої експонентної, або плаваючої, форми. Дійсне число r має вигляд

r = ±2e* m

Подання числа складається з трьох елементів:

  1.  знак числа - плюс або мінус. Під знак числа приділяється один біт у двійковому поданні, він розташовується в старшому, тобто знаковому розряді. Одиниця відповідає знаку мінус, тобто від’ємному числу, нуль - знаку плюс. У нуля знаковий розряд також нульовий;
  2.  показник ступеня e, його називають порядком або експонентою. Експонента вказує ступінь двійки, на яку множиться число. Експонента може бути як додатною, так і від’ємною (для чисел, менших одиниці). Під експоненту приділяється фіксоване число двійкових розрядів, звичайно вісім або одинадцять, розташованих у старшій частині двійкового подання числа, відразу слідом за знаковим розрядом;
  3.  мантиса m являє собою фіксовану кількість розрядів двійкового запису дійсного числа в діапазоні від 1 до 2:
  4.  1 <= m<2

Варто підкреслити, що ліва нерівність нестрога - мантиса може рівнятися одиниці, а права - строга, мантиса завжди менше двох. Розряди мантиси включають один розряд цілої частини, що через наведену нерівність завжди дорівнює одиниці, і фіксована кількість розрядів дробної частини. Оскільки старший двійковий розряд мантиси завжди дорівнює одиниці, зберігати його необов'язково, і у двійковому коді він відсутній. Фактично двійковий код зберігає тільки розряди дробової частини мантиси.

У мові С# дійсним числам відповідають типи float й double. Елемент типу float займає 4 байти, у яких один біт приділяється під знак, вісім - під порядок, інші 23 - під мантису (насправді, у мантисі 24 розряду, але старший розряд завжди дорівнює одиниці, тому зберігати його не потрібно). Тип double займає 8 байтів, у них один розряд приділяється під знак, 11 - під порядок, інші 52 - під мантису. Насправді в мантисі 53 розряду, але старший завжди дорівнює одиниці й тому не зберігається. Оскільки порядок може бути додатнім і від’ємним, у двійковому коді він зберігається в зміщеному виді: до нього додається константа, рівна абсолютній величині максимального по модулю від’ємного порядку. У випадку типу float вона дорівнює 127, у випадку double - 1023. Таким чином, максимальний по модулю від’ємний порядок представляється нульовим кодом.

Арифметичний тип із плаваючою крапкою

Ім'я типу

Системний тип

Діапазон

Точність

Float

System.Single

- 3. 402823e38 … + 3...402823e38

7 цифр

Double

System.Double

- 1. 79769313486232e308... 1.79769313486232e308

15-16 цифр

Основним типом є тип double, саме він найбільш природний для комп'ютера. У програмуванні треба по можливості уникати типу float, тому що його точність недостатня, а процесор однаково при виконанні операцій перетворить його в тип double. (Один з деяких випадків, де застосування типу float виправдано, - тривимірна комп'ютерна графіка.)

Кілька прикладів подання дійсних чисел у плаваючій формі:

  1.  1.0 = +20*1.0

Тут порядок дорівнює 0, мантиса - 1. У двійковому коді мантиса складається з одних нулів, тому що старший розряд мантиси (завжди одиничний) у коді відсутній. Порядок зберігається у двійковому коді в зміщеному виді, він дорівнює 127 у випадку float й 1023 у випадку double;

  1.  3.5 = +21*1.75

Порядок дорівнює одиниці, мантиса складається із трьох одиниць, з яких у двійковому коді зберігаються дві: 1100...0; зміщений порядок дорівнює 128 для float й 1024 для double;

  1.  0. 625 = +2-1*1.25

Порядок від’ємний і дорівнює -1, дробова частина мантиси дорівнює 0100...0; зміщений порядок дорівнює 126 для float й 1022 для double;

  1.  100.0 = +26*1.5625

Порядок дорівнює шести, дробова частина мантиси дорівнює 100100...0; зміщений порядок дорівнює 133 для float й 1029 для double.

При виконанні додавання двох додатніх плаваючих чисел відбуваються наступні дії:

  1.  вирівнювання порядків. Визначається число з меншим порядком. Потім послідовно його порядок збільшується на одиницю, а мантиса ділиться на 2, поки порядки двох чисел не зрівнюються. Апаратно розподіл на 2 відповідає зрушенню двійкового коду мантиси вправо, так що ця операція виконується швидко. При зрушеннях праві розряди губляться, через це може відбутися втрата точності (у випадку, коли праві розряди ненульові);
  2.  додавання мантис;
  3.  нормалізація: якщо мантиса результату стала дорівнює або перевищила двійку, то порядок збільшується на одиницю, а мантиса ділиться на 2. У результаті цього мантиса попадає в інтервал 1 <=m<2. При цьому можлива втрата точності, а також переповнення, коли порядок перевищує максимально можливу величину.

Вирахування виробляється аналогічним образом. При множенні порядки складаються, а мантиси перемножуються як цілі числа, після чого в результату праві розряди відкидаються.

Дії із плаваючими числами через помилки округлення лише приблизно відбивають арифметику дійсних чисел. Так, якщо до великого плаваючого числа додати дуже маленьке, то воно не зміниться. Дійсно, при вирівнюванні порядків всі значущі біти мантиси меншого числа можуть вийти за межі розрядної сітки, у результаті чого воно стане рівним нулю. Таким чином, із плаваючими числами можлива ситуація, коли

a+b = a при b 0

Більше того, для додавання не виконується закон асоціативності:

a+(b+c) (a+b)+c

Дійсно, нехай ε - максимальне плаваюче число серед чисел, що задовольняють умові

1.0+? = 1.0

(наведені вище міркування показують, що такі числа існують). Тоді

(1.0+ε)+ε 1.0+(?+?)

оскільки ліва частина нерівності дорівнює одиниці, а права строго більше одиниці (це слідує з максимальності числа ε).

Число ε часто називають машинним эпсилоном або, менш коректно, машинним нулем, оскільки при додатку до одиниці воно поводиться як нуль. Величина машинного эпсилона характеризує точність операцій комп'ютера. Вона приблизно однакова для всіх сучасних комп'ютерів: більшість процесорів працюють із восьмибайтовими плаваючими числами (тип double у С#), а арифметика плаваючих чисел підкоряється строгим міжнародним стандартам.

Визначимо величину машинного епсилону для типу double. Число 1.0 записується в плаваючій формі як 1.0 = +20*1.0.

Порядок плаваючого числа 1.0 дорівнює нулю. При додаванні 1.0 із числом ε виконується вирівнювання порядку шляхом багаторазового зрушення мантиси числа ε вправо й збільшення його порядку на 1. Оскільки всі розряди числа ε повинні в результаті вийти за межі розрядної сітки, повинно бути виконане 53 зрушення. Порядок числа ε після цього повине стати рівним порядку числа 1.0, тобто нулю. Отже, споконвічно порядок числа ε повине бути рівним -53:

ε = 2-53*m

де m - число в діапазоні від одиниці до двох. Таким чином, величина машинного эпсилона становить приблизно

2-53 10-16

Приблизно точність обчислень становить 16 десяткових цифр. (Це також можна оцінити в такий спосіб: 53 двійкових розрядів становлять приблизно 15.95 десяткових, оскільки 53/log210 53/3.321928 15.95.)

У випадку чотирьохбайтових плаваючих чисел (тип float мови С#) точність обчислень становить приблизно 7 десяткових цифр. Це дуже мало, тому тип float надзвичайно рідко застосовується на практиці. До того ж процесор сконструйований для роботи з восьмибайтовими дійсними числами, а при роботі із чотирьохбайтовими він однаково спочатку приводить їх до восьмибайтового типу. У програмуванні варто уникати типу float і завжди користуватися типом double.

Крім втрати точності, при операціях з дійсними числами можуть відбуватися й інші неприємності:

  1.  переповнення - коли порядок результату більше максимально можливого значення. Ця помилка часто виникає при множенні великих чисел;
  2.  зникнення порядку - коли порядок результату від’ємний і занадто великий по абсолютній величині, тобто порядок менше мінімально припустимого значення. Ця помилка може виникнути при діленні маленького числа на дуже велике або при множенні двох дуже маленьких по абсолютній величині чисел.

Крім того, некоректною операцією є ділення на нуль. На відміну від операцій із цілими числами, переповнення й зникнення порядку вважаються помилковими ситуаціями й приводять до апаратного переривання роботи процесора. Програміст може задати реакцію на переривання - або аварійне завершення програми, або, наприклад, при переповненні привласнювати результату спеціальне значення плюс або мінус нескінченність, а при зникненні порядку - нуль. Помітимо, що серед двійкових кодів, що представляють плаваючі числа, є кілька спеціальних значень. Перелічимо деякі з них:

  1.  нескінченно велике число - це плаваюче число з дуже великим додатнім порядком й, таким чином, дуже велике по абсолютній величині. Воно може мати знак плюс або мінус;
  2.  нескінченно мале, або денормалізоване, число - це ненульове плаваюче число , тобто дуже маленьке по абсолютній величині;
  3.  Not a Number, або Na - двійковий код, що не є коректним поданням якого-небудь дійсного числа.

Будь-які операції з константою Na приводять до переривання, тому вона зручна при налагодженні програми - нею перед початком роботи програми ініціалуються значення всіх дійсних змінних. Якщо в результаті помилки програміста при обчисленні виразу використається змінна, котрої не було привласнено ніякого значення, то відбувається переривання через операцію зі значенням Na і помилка швидко відслідковується. На жаль, у випадку цілих чисел такої константи немає: будь-який двійковий код представляє деяке ціле число.

Дійсні константи записуються у двох формах - з фіксованою десятковою крапкою або в експонентному виді. У першому випадку крапка використається для поділу цілої й дробової частин константи. Як ціла, так і дробова частини можуть бути відсутніми. Приклади:

1.2, 0.725, 1., .35, 0.

У трьох останніх випадках відсутня або дробова, або ціла частина. Десяткова крапка повинна обов'язково бути присутня, інакше константа вважається цілою. Відзначимо, що в програмуванні саме крапка, а не кома, використається для відділення дробової частини; кома зазвичай служить для поділу елементів списку.

Експонентна форма запису дійсної константи містить знак, мантису й десятковий порядок (експоненту). Мантиса - це будь-яка позитивна речовинна константа у формі з фіксованою крапкою або цілою константою. Порядок указує степінь числа 10, на яку домножується мантиса. Порядок відокремлюється від мантиси буквою "e" (від слова exponent), вона може бути прописною або рядковою. Порядок може мати знак плюс або мінус, у випадку позитивного порядку знак плюс можна опускати. Приклади:

1.5e+6 константа еквівалентна 1500000.0

1e-4 константа еквівалентна 0.0001

-.75E3 константа еквівалентна -750.0

Задача 10.1

Написати програму: Обчислити значення функції , коли х змінюється від А до В з кроком H. Результати вивести у вигляді таблиці " № розр.- Х- У". Врахувати не значимі значення аргументу. Використати відомі методи організації циклів.

Лістинг 10.1.. З використанням циклу for

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace ConsoleApplication3

{

class Program

{

static void Main(string[] args)

{

double a, b, h;

int i=0;

a = double.Parse(Console.ReadLine());

b = double.Parse(Console.ReadLine());

h = double.Parse(Console.ReadLine());

for (double x = a; x <= b; x = x + h)

{

i++;

if ((1 - x * x < 0) | (Math.Sin(1 - x) == 0))

{

Console.WriteLine(i + " " + x + " рішення немає ");

}

else

{

double y = Math.Sqrt(1 - x * x) / Math.Tan(1 - x);

Console.WriteLine(i + " " + x + " " + y);

} } } }}

Лістинг 10.2. З використанням циклу while

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace ConsoleApplication3

{

class Program

{

static void Main(string[] args)

{

double a, b, h;

int i=0;

a = double.Parse(Console.ReadLine());

b = double.Parse(Console.ReadLine());

h = double.Parse(Console.ReadLine());

double x = a;

while (x<=b)

{

i++;

if ((1 - x * x < 0) | (Math.Sin(1 - x) == 0))

{

Console.WriteLine(i + " " + x + " рішення немає ");

}

else

{

double y = Math.Sqrt(1 - x * x) / Math.Tan(1 - x);

Console.WriteLine(i + " " + x + " " + y);

}

x = x + h;

}

}

}

}

Лістинг 10.4.. З використанням циклу do while

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace ConsoleApplication3

{

class Program

{

static void Main(string[] args)

{

double a, b, h;

int i=0;

a = double.Parse(Console.ReadLine());

b = double.Parse(Console.ReadLine());

h = double.Parse(Console.ReadLine());

double x = a;

do

{

i++;

if ((1 - x * x < 0) | (Math.Sin(1 - x) == 0))

{

Console.WriteLine(i + " " + x + " рішення немає ");

}

else

{

double y = Math.Sqrt(1 - x * x) / Math.Tan(1 - x);

Console.WriteLine(i + " " + x + " " + y);

}

x = x + h;

}

while (x <= b);

}

}

}

Проаналізуйте наведені задачі, перевірте їх працездатність в середовищі програмування.


 

А также другие работы, которые могут Вас заинтересовать

54252. Математика – це цікаво! Математика – це потрібно! 59 KB
  Математика – це цікаво Математика – це потрібно Важко обійтися сьогодні без математики Усім – і дрослим і дітям – потрібна її допомога у повсякденному житті. Колись в Америці було обіцяно велику премію тому хто напише книжку під назвою Як людина жила без математикиâ€. За більше ніж 30 років викладання математики в школі я переконалася що одним із шляхів удосконалення навчання учнів такому складному предмету є нетрадиційність у його репрезентації школярам.
54253. Властивості степеня з цілим показником 795 KB
  Властивості степеня з цілим показником. Сформувати прикладну необхідність вивчення властивостей степеня з натуральним показником. Які операції ви вмієте виконувати над числами Прочитати число; записати; порівняти; додати; відняти; помножити; поділити; піднести до степеня. Які саме вирази ми зараз вивчаємо Вирази зі степенями То які операції нам потрібно вміти виконувати над виразами зі степенями Прочитати вирази зі степенями; записати; порівняти; додати; відняти; помножити; поділити; піднести до степеня.
54254. Функціональна залежність в системі прикладних задач шкільного курсу математики 631.08 KB
  Стаття містить приклад класифікації прикладних задач та аналіз способу їх розв’язання, узагальнений алгоритм розв’язування задач прикладного характеру. Основне її завдання спонукати використання прикладних задач при вивченні функціональної лінії шкільного курсу математики.
54255. Письмове додавання трицифрових чисел із переходом через розряд 716 KB
  Ознайомити учнів із прийомом письмового додавання трицифрових чисел з переходом через розряд; формувати навички письмового додавання і віднімання трицифрових чисел; виховувати почуття взаємодопомоги, вміння працювати в команді, аргументовано відстоюючи власну думку; розвивати охайність при виконанні робіт.
54256. Відсоткові розрахунки, Один день праці на підприємстві 102.5 KB
  Мета уроку: Формування в учнів вмінь самостійно визначати тип задачі на відсотки та навичок обчислень відсотка від числа, числа за його відсотком та відсоткового відношення двох чисел; розкрити практичну необхідність вивчення теми «Відсотки» в шкільному курсі; розвивати інтерес до математики, прагнення до самовдосконалення; виховувати почуття колективізму та відповідальності перед колективом.
54257. Умножение и деление рациональных чисел 174.5 KB
  Цель: развивать социальную компетентность используя самооценку и взаимооценку; развивать компетентность самообразования стимулируя познавательный интерес; развивать коммуникативную компетентность организовывая работу в парах; обобщить знания учащихся об умножении и делении рациональных чисел; экономическое воспитание. Тема урока Умножение и деление рациональных чисел. Как будет называться наше АО вы узнаете по своим ответам на мои вопросы составив слово Теория первична Учитель ...
54258. Закрепление сложения и вычитания трехзначных чисел 333 KB
  Ребята сегодня у нас необычный урок математики к нам пришли гости. Какие вы второклассники Ждут вас сегодня затеи и задачи Игры шутки всё для вас Пожелаю вам удачи За работу в добрый час Ребята за ваши правильные и полные ответы я вам буду раздавать наклейки. Ребята наши гости решили поиграть с вами в прятки спрятались от вас.
54259. Переместительное свойство сложения 22.5 KB
  Материалы необходимые для урока: изображение дерева изображения листьев Ход урока: Давайте посчитаем сколько же листьев на нашем дереве Сколько листьев справа от дерева 4 Сколько листьев слева от дерева 3 Где листьев больше а где меньше 3.
54260. Видатні українські математики. Застосування різних способів розкладання многочленів на множники 619.5 KB
  1 учень: Остроградський Михайло Васильович народився у вересні 1801 року на Полтавщині. 2 учень: Походив з родини збіднілих дворян які мали глибоке козацьке коріння. 3 учень: У 8 років його віддали до гімназії у Полтаві але хлопчик жвавої та веселої вдачі звикший до роздольного життя у рідному селі особливою старанністю не відзначався. Учень: Блискуче закінчивши університет Михайло рік живе у батька а потім вирішивши присвятити себе математиці знову повертається до Харкова для вдосконалення своїх знань.