[ЗМІСТ]      [Далі]       [Назад]      [Початок розділу]

 

5.2. Числові типи даних

 

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

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

 

5.2.1. Натуральний тип

 

      Нехай N - множина всіх натуральних чисел, m Î N. Назвемо m - обмеженою множиною натуральних чисел її підмножину

 

       N  = {n Î N:  n <= m}.¦

        m

      На множині N  задамо обмежені арифметичні операції

                  m

таким чином. Нехай n, k Î N ,  тоді

                           m

 

    n +  k = якщо n+k <= m то n+k

       m                                                     (5.1)

             інакше відмова {переповнення натуральних чисел};

 

    n *  k = якщо n*k <= m то n*k

       m                                                     (5.2)

             інакше відмова {переповнення натуральних чисел};

 

    n -  k = якщо n >= k то n-k

       m                                                     (5.3)

             інакше відмова {різниця не визначена};

 

а також вже згадувані функції div і mod:

 

       n = k * (n div k) + (n mod k),                      (5.4)

       0 <= (n mod k) < k.                                 (5.5)

 

Всі названі операції часткові.

      Нехай m - натуральне число. Назвемо m - обмеженим натуральним типом або коротше натуральним типом, якщо значення m мається на увазі, множину Nm, на якій задані перераховані вище операції (5.1)-(5.5) і стандартний набір відношень рівності і нерівностей

 

       { Nm;  +, *, -, div, mod; =, <>, >, >=, <, <= },

причому обмежені арифметичні операції будемо позначати попередніми символами.¦

      Якщо передбачити, що арифметичний операційний пристрій виконавця AB виконує арифметичні операції над обмеженими натуральними числами, то прикладом програми для такого виконавця, визначимо його ABN, може служити

 

      Приклад 5.3. Алгоритм обчислення найбільшого спільного дільника двох натуральних чисел за допомогою методу Евкліда

 

    алгоритм НОД це

       змін M, N, U, V: нат;

    поч

       взяти (M, N);

       U <- M; V <- N;

       поки U<>V повт

          якщо U<V то V <- V-U

          інакше U <- U-V кр

       кц;

       показати (U)

    ка.

 

5.2.2. Цілий тип

 

      Нехай знову n - натуральне число, Z - множина всіх цілих чисел. Назвемо n - обмеженою множиною цілих чисел її підмножину

 

       Z  = {z Î Z:  ¦z¦ <= n}.¦

        n

 

    Для m, k Î Z  визначимо

                n

 

    m +  k = якщо ¦m+k¦ <= n то m+k

       n                                                (5.6)

             інакше відмова (переповнення цілих чисел);

 

    m *  k = якщо ¦m*k¦ <= n то m*k

       n                                                (5.7)

             інакше відмова (переповнення цілих чисел);

 

    m -  k = якщо ¦m-k¦ <= n то m-k

       n                                                (5.8)

             інакше відмова (переповнення цілих чисел);

 

    m div k = sign(m) * sign(k) * (¦m¦ div ¦k¦);           (5.9)

    m mod k = m - (m div k) * k.                           (5.10)

 

      Назвемо n - обмеженим цілим типом або коротше цілим типом, якщо значення n мається на увазі, множину Zn, на якій задані операції (5.6)-(5.10) і стандартний набір відношень рівності та нерівності

 

       { Zn;  +, *, -, div, mod; =, <>, >, >=, <, <= }.¦

Тим же способом, що і вище, отримуємо виконавець ABZ. Об'єднавши можливості ABN і ABZ, отримаємо виконавець ABNZ. Останній передбачає одночасне використання обох типів даних.

      Добре відомо, що множина цілих чисел Z є розширенням множини N. Для випадку обмежених числових множин включення має місце не завжди. Скажемо, що відображення g: А -> В множини А у множину В називається вкладенням, якщо з g(х) = g(у) випливає х = у " х, у Î A. Тоді справедливе

 

      Твердження 5.4. Якщо m< n, то Nm Ì Zn, тобто існує вкладення

 

       g:  N  -> Z ,

            m     n

таке, що для будь-яких i, j Î Nm  виконані співвідношення

 

       g(i +  j) = g(i) +  g(j);

            m            n

 

       g(i *  j) = g(i) *  g(j);

            m            n

 

       g(i -  j) = g(i) -  g(j);

            m            n

 

       g(i div j) = g(i) div g(j);

 

       g(i mod j) = g(i) mod g(j).¦

 

      Займемося тепер дійсними числами.

 

5.2.3. Дійсний тип

 

      Нехай х - дійсне число, х Î R і t=round(х, р, b). В арифметичному виконавцеві AB число х зображається наближеним р - розрядним представленням з плаваючою крапкою за основою b з надлишком q - позначення float       (х) = (f, r), - так що

                              р, b, q

 

            r-q

       f * b   = t;                                         (5.11)

 

        -1

       b   <= ¦f¦ < 1;                                      (5.12)

 

        р

       b  * f - ціле число.¦                                (5.13)

 

      Число f називається мантисою наближення, а r - його порядком. Умови (5.12) та (5.13) дозволяють вибрати мантису і порядок однозначно.

      Умова (5.12) називається умовою нормалізованості, а умова (5.13) гарантує, що в числі f в точності р цифр. Наприклад,

 

    float      (0.02241383) = (0.22414,4);

         5,10,5

 

    float      (2997934580) = (0.299793,10);

         6,10,0

 

 

    float      (-3.14159265) = (-0.3142,9).

         4,10,8

 

Назвемо (p,b,q,d) - обмеженою множиною дійсних чисел множину наближених p - розрядних представлень з плаваючою крапкою за основою b з надлишком q та максимальним порядком d всіх дійсних чисел x Î D(q,d):

 

    R        = { (f,r): (f,r)=float     (x); x Î D(q,d); r Î N },

     p,b,q,d                       p,b,q                      d

 

де інтервал представлення D(q, d) вибирається з умов (5.12) та (5.13)

              r-q    r-q     d-q

       ¦f¦ * b    < b    <= b   .

 

Далі

              r-q     -1   r-q     -q-1

       ¦f¦ * b    >= b  * b    >= b    .

 

Отже,

                                      -q-1           d-q

       D(q, d) = {0} È {х Î R: х   = b     <= ¦х¦ < b   = х   }.

                                 min                        max

Причому інтервал

 

       U = {х: ¦х¦ > х   }

                      max

називається інтервалом переповнення, а інтервал

 

       V = {х: ¦х¦ < х   } \ {0}

                      min

- інтервалом антипереповнення або зникнення порядку.

 

Визначимо тепер обмежену наближену  р - розрядну операцію додавання

 

       х +. у = якщо х +  у = 0 то 0

                        р

                інакше якщо ¦х +  у¦ < х     то

                               р        max

 

                         якщо ¦х +  у¦ >= х     то х +  у

                                  р        min        р      (5.14)

 

                         інакше відмова {антипереповнення}

                      інакше відмова {переповнення}.

 

Віднімання, множення та ділення визначаються аналогічно.

 

      Дійсним типом даних назвемо множину Rр, b, q, d, на якій задані обмежені наближені арифметичні операції вигляду (5.14) і стандартний набір відношень рівності і нерівностей

 

       { Rр, b, q, d;+, -, *, /; =, <>, >, >=, <, <= }.¦

 

      Розглянемо зв'язок між Zn та Rр, b, q, d.

 

      Властивість 5.4. Якщо ¦n¦ <= bp, то round(n, р, b) = n.

      Доведення. Якщо ¦n¦= bp,  то наше твердження випливає з властивостей 5.3 і 5.1 функції округлення.

                                        r-1         r

    Нехай ¦n¦< bp.  Виберемо r так, щоб b   < ¦n¦ < b.  Тоді

 

                                   r-p    p-r

       round(n, р, b) = sign(n) * b   * [b   * ¦n¦ + 1/2] =

 

                                 r-p   p-r

                    = sign(n) * b   * b   * ¦n¦ = n,

 

            r-1   р             r    р      p-r

оскільки з b   < b  слідує, що b  < b  або b   > 1.¦

 

      Тепер отримаємо

                                min(р, d)-q

    Твердження 5.5. Нехай n < b,           . Тоді функція

 

float       (х) є вкладенням Z  в R          :  Z  -> R          ,

     р, b, q                  n    р, b, q, d    n     р, b, q, d

 

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

      Доведення. Нехай р < d, w - операція додавання, віднімання

                        p-q    р

або множення. Оскільки b    < b , то для будь-яких u, v Î Zn таких, що ¦u w v¦< n як функцію вкладення g можна взяти функцію round.

Тоді в силу властивості 5.4

 

       g(u) w g(v) = round(u, р, b) w round(v, р, b) = u w v =

 

     = round(u w v, р, b) = g(u w v).

 

                       d-q    p-q    р

      Якщо d < р,  то b    < b    < b  і наведені вище  міркування можна повторити дослівно.¦

      Операційний пристрій R дійсних чисел (його називають арифметчним пристроєм чисел з плаваючою крапкою) визначається аналогічно попереднім.

      Нижче наведене схематичне зображення виконавця ABRZN, що вміщує бульове та три типи арифметичних операційних пристроїв.

 

                                     ---------------

                                     ¦             ¦

             ABRZN                   ¦ C + IF + Lw ¦

                                     L--------------

                                        ^   ^

             ----------------------------   ¦

             ¦                              ¦

       ------v------   ---------------------v-------

       ¦ -----     ¦   ¦   -----   -----   -----   ¦

       ¦ ¦   ¦     ¦   ¦   ¦   ¦   ¦   ¦   ¦   ¦   ¦

       ¦ ¦ B ¦     ¦   ¦   ¦ N ¦   ¦ Z ¦   ¦ R ¦   ¦

       ¦ L----     ¦   ¦   L----   L----   L----   ¦

       L----- БОП --   L--------------- АОП --------

 

      На практиці в реальних ЕОМ звичайно реалізується виконавець ABRZ, який має три типи даних: бульовий, дійсний, цілий, який ми будемо називати простим стандартним арифметичним виконавцем.

 

      Приклад 5.4. Розглянемо ABRZ - алгоритм наближеного з точністю e>0 обчислення значення функції у=sin x, представленої у вигляді ряду Тейлора:

               3    5                  2k+1

              х    х              k   х

       у= х - -- + -- - ... + (-1) * ------- + ...

              3!   5!                (2k+1)!

      Аналогічно прикладу 3.16 обчислення будемо проводити доти, поки модуль чергового доданку з нашої суми не стане меншим заданого e. Тоді легко отримати наступний фрагмент:

 

       взяти (X, Eps);

       Y <- 0; А <- X; K <- 1; Z <- X*Х;

       поки abs(А)>=Eps повт

          Y <- Y+А;                                        (5.15)

          K <- K+2;                                        (5.16)

          А <- -A*Z/(K*(K-1))                              (5.17)

       кц;

       показати (Y).

 

Особливої уваги заслуговує виконання присвоєнь (5.15)-(5.17). Присвоєння (5.15) та (5.16) виконуються різними операційними пристроями, відповідно, R і Z. Прі виконанні присвоєння (5.17) відбувається передача числа k з операційного пристрою Z в операційний пристрій R, що супроводжується обчисленням функції float.

      Відомо, що при ¦х¦>>1, значення степеня х будуть зростати спочатку набагато швидше, ніж значення факторіала. Тоді при значеннях х близьких до хmax можливо, що відношення степеня до факторіала потрапить в область переповнення, що викличе відмову в роботі алгоритму. Для перестороги від цієї ситуації скористаємося властивостями функції sin. Конкретно, врахуємо непарність sin x і застосовуючи правила приведення зведемо аргумент х до інтервалу [0, p/2].

      Остаточно отримаємо:

 

    алгоритм SinX це

       конст Pi= 3.14159265;

       змін X, Eps, А, Z, Y: дійсн;

             K, M: ціл;

    поч

       взяти (X, Eps);

       якщо X<0 то           { sin(- х) = -sin(х) }

          M <- -1; X <- -X

       інакше

          M <- 1

       кр;

       А <- 2*Pi;

       поки X>=А повт         { sin(х-2p) = sin(х) }

          X <- X-A

       кц;          { 0<= х< 2p }

       якщо X>=Pi то         { sin(х) = -sin(х-p) }

          M <- -M; X <- X-Pi

       кр;          { 0<= х< p }

       якщо X>=Pi/2 то       { sin(х) = sin(p-х) }

          X <- Pi-X

       кр;          { 0<= х< p/2 }

       Y <- 0; А <- X; K <- 1; Z <- X*Х;

       поки abs(А)>=Eps повт

          Y <- Y+А;

          K <- K+2;

          А <- -A*Z/(K*(K-1))

       кц;

       Y <- Y*M;

       показати (Y)

    ка.

 

5.2.4. Двійкове кодування

 

      Пам'ять ЕОМ представляє собою послідовність 8-розрядних клітинок - байтів. Кожний розряд - його називають бітом - може приймати одне з двох значень: визначимо їх 0 і 1 (насправді байт містить 9 бітів: біт перевірки на непарність). Тоді байт цілком приймає 28 = 256 різних значень, які можна вважати натуральними числами від 0 до 255, представленими в позиційному записі за основою 2. Таким чином, за допомогою одного байта можна кодувати будь-яке натуральне число з множини N255, чого явно недостатньо. Тому пристроєм ЕОМ передбачене об'єднання байтів в групи по два і по чотири, а для деяких типів ЕОМ - по вісім або навіть по шістнадцять.

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

      Розглянемо деякі загальноприйняті способи кодування цілих та дійсних чисел.

      Стандартним є кодування цілого числа за допомогою двох байтів. Один біт використовується для кодування знаку числа, отже, 15 бітів, що залишилися в сукупності можуть приймати одне із 215 = 32768 значень. Таким чином стандартним обмеженням множини цілих чисел є Z32767.

      Одне з стандартних кодувань дійсного числа - чотирибайтове. Спосіб використання цих чотирьох байтів для різних типів ЕОМ може розрізнюватися. Наприклад, в Єдиному Сімействі ЄС ЕОМ був прийнятий наступний спосіб кодування. Мантиса числа представлена в позиційному записі за основою 16. Для її запису використано 3 байти. Отже b = 16, р = 6, оскільки в кожному байті можна розташувати 2 цифри за основою 16. Оскільки 166 = 16777216, то десятковий запис мантиси складався б з семи значущих цифр. Байт, що залишився, використовується для кодування знаку числа (0 - позитивне число, 1 - негативне) і його порядку. Таким чином, порядок займає 7 бітів і, отже, d = 27 - 1 = 127. Надлишок q = 64. Тоді

 

                -65           -79          63           75

       х    = 16    = 5.4 * 10,    х   = 16   = 7.2 * 10  .

        min                         max

 

          +

          -     r                     f

         <-><------>  <-------------------------------->

         -----------  ----------  ----------  ----------

         ¦ ¦       ¦  ¦        ¦  ¦        ¦  ¦        ¦

         L-+--------  L---------  L---------  L---------

            байт 1      байт 2      байт 3      байт 4

 

      Отже, засобами ЄС ЕОМ реалізувався простий стандартний виконавець

                    6   7      15

тель ABRZ { 6, 16, 2,  2 - 1; 2  - 1 }.

 

      Для персональних ЕОМ типу IBM PC прийнятий інший спосіб кодування. Знак кодується в старшому розряді останнього байта. Мантиса числа займає три молодщих байти без одного біта. Вона записана в двійковій

 

          +

          -       r                     f

         <-><-----------><------------------------------>

         -----------  -----------  ----------  ----------

         ¦ ¦       ¦  ¦ ¦       ¦  ¦        ¦  ¦        ¦

         L-+--------  L-+--------  L---------  L---------

            байт 4       байт 3      байт 2      байт 1

 

системі числення. Отже, b = 2, р = 23. Мантиса завжди нормалізована і має 23 явних розряди і один неявний. Нормалізація виконується так, що старша значуща одиниця коду мантиси завжди розташовується перед позиційною крапкою. Цей розряд в коді мантиси не вказується, але завжди мається на увазі. Отже, мантиса має вигляд

 

       f = 1.a1 а2 а3... а23,

 

де аk  - двійкова цифра в k-му розряді мантиси (з вагою 2-k  ).

      Оскільки 224 = 16 777 216, то десятковий запис мантиси складається з семи значущих цифр, але гарантовано правильний результат дають тільки шість. Порядок кодується одним байтом d = 28 - 1 при надлишку q = 127. Отже, з урахуванням нової умови нормалізованості

 

               -127           -39         128           38

       х    = 2     = 5.9 * 10,    х   = 2    = 3.4 * 10. 

        min                               max

 

                                        7      8        15

    Отримуємо виконавець ABRZ { 23, 2, 2 -1,  2  - 1;  2   - 1 }.

 

      Відмітимо, що ЕОМ забезпечують також можливість реализації інших виконавців сімейства ABRZ, наприклад, для персональних ЕОМ Zn при n = 231 - 1 = 2 147 483 647 та Rр, b, q, d при р = 52, d = 211-1. Вказаний виконавець дозволяє оперувати з 16 десятковими значущими цифрами мантиси, що істотно підвищує точність обчислень.

 

      Для кодування бульових значень очевидно досить одного біта. Однак байтова структура пам'яті ЕОМ робить такий спосіб кодування не оптимальним, оскільки витягання довільного біта з байта - операція не елементарна, а вимагає програмування.

      Внаслідок сказаного, стандартним кодуванням бульових величин вважається байтове кодування. Значення Хиб звичайно кодується нульовим байтом, а всі інші коди вважаються кодами значення Іст.

      Розглянемо тепер як програмуються прості типи даних. Бульовий тип даних ми розглянули раніше. Тепер зупинимося на числових типах даних.

 

5.3. Програмування числових типів даних

 

5.3.1. Натуральний тип

 

      Мова Паскаль. Турбо-Паскаль надає декілька можливостей програмування натурального типу даних. Зокрема, є 2 стандартних натуральних типи даних: byte та word. Для типу byte обмеження m множини Nm дорівнює 255 (28 - 1), а для типу word – 65535 (216 – 1).

Приклади описів змінних:

 

       var N, M, L: byte;

       var K, I: word;

 

Змінна типу byte займає в пам'яті один байт, а типу word – два байти.

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

      Зауваження 5.3. Контроль за значеннями, що приймаються змінними типів byte та word, звичайно не проводиться. Але у інтегрованому середовищі Турбо-Паскаль можна встановити опцію компілятора “Overflow checking” з метою фіксації переповнення.¦

 

      У мові Сі для програмування натурального типу даних використовується ідентифікатор unsigned, який насправді означає ціле число без знаку. Отже натуральний тип розглядається у Сі як різновид цілого типу даних та більш докладно описаний у наступному підрозділі.

 

5.3.2. Цілий тип

 

      У мові Паскаль реалізовано два цілих типи: звичайний та довгий. Для опису змінних цих типів використовуються відповідно ідентифікатори integer та longint. До типу integer відносяться всі цілі числа з диапазону від -maxint до maxint, де maxint - вбудована константа (максимальное ціле число). Значення maxint дорівнює 32767 (215-1). До типу longint відносяться цілі числа з диапазону від -231 до 231-1, тобто від -2 147 483 648.до.2 147 483 647. Приклади описів змінних цілого типу:

 

       var I, J, K: integer;

       var A, B, C: longint;

      Над елементами х, у цілого типу визначені наступні:

 

    a) операції: додавання х+у; віднімання x-y;  множення х*у;  частка від ділення х div у; остача від ділення х mod у.

      Зауваження 5.4. При виконанні арифметичних операцій переповненя звичайно не виявляється, повідомлення про помилку не видається, результат непередбачуваний. Один з способів боротьби з переповненням реалізований у прикладі 2P. Виявити помилку переповнення можна так само, як і для натурального типу даних.¦

 

    b) функції:

       abs(х) - обчислення модуля х;

       sqr(х) - обчислення х2;

 

                ¦ true,  х - непарне число,

       odd(х) = <

                ¦ false, х - парне число;

 

                 ¦ х-1,    х >= -maxint,

       pred(х) = <

                 ¦ maxint,  х = -maxint-1,

 

                 ¦ х+1,         х < maxint,

       succ(х) = <

                 ¦ -(maxint+1), х = maxint,

 

       random(х) - генерація випадкового числа з діапазону [0, х].

 

      Приклад 1P. Дано натуральне n>= 1 та цілі а1,..., аn. Припустимо, що а1,..., аn - попарно різні. Потрібно визначити найбільший член аk послідовності а1,..., аn разом з його порядковим номером k.

 

    program Zmax;

       var J, K, N: word;

           А, M: integer;

    begin

       write('n=? '); readln(N);

       write(' 1-? '); readln(M);

       K:= 1;

       for J:=2 to N do begin

          write(J:2,'-? '); readln(А);

          if А>M then begin M:= А; K:= J end

       end;

       writeln(' Найбільше= ', M:2,' Номер= ', K:1)

    end.

 

      Приклад 2P. Програма обчислення НСД та НСК двох цілих чисел.

 

    program Euclid;

       var X, Y, M, N: integer;

    begin

       write('х, у=? '); readln(X, Y);

       M:= abs(X); N:= abs(Y);

       while M<>N do

          if M>N then M:= M-N

          else N:= N-M;

       writeln('НСД( ', X:2,',', Y:2,' )= ', M:2);

       N:= abs(X) div M;

       if N>maxint div abs(Y) then writeln(' Переповнення')

       else writeln('НСК( ', X:2,',', Y:2,' )= ', N*abs(Y):2)

    end.

 

      У мові Сі існує декілька цілих типів даних на основі базового типу int. Ці типи задають з використанням так званих «кваліфікаторів»: short (короткий), long (довгий) а також unsigned (без знаку), signed (зі знаком). Наприклад:

 

      signed int a, b, c;

      signed short int d;

      unsigned long int x, y;

 

Якщо вказано кваліфікатори, int можна опустити. Якщо не вказано signed або unsigned, то за угодою вважається signed. Наприклад:

 

      int a, b, c;

      short d;

      unsigned long x,y;

 

У Турбо Сі під змінні типів short int та int відводиться 2 байти, а під змінні типу long int – 4 байти.

      Для реалізації цілого типу надалі ми будемо використовувати int або long int, для реалізації натурального типу – unsigned або unsigned long. Диапазони значень для типів int та long int співпадають з відповідними диапазонами для типів integer та longint Паскаля. Диапазон значень типу unsigned співпадає з диапазоном значень типу word Паскаля. Дані типу unsigned long змінюються в диапазоні від 0 до 232-1, тобто 4 294 967 296.

      Над елементами х, у цілого типу визначені наступні:

 

    a) операції: додавання х+у; віднімання x-y;  множення х*у;  частка від ділення х / у; остача від ділення х % у.

      Зауваження 5.4 вірне також для Сі.

 

    b) функції:

       abs(х) - обчислення модуля х (int x);

       labs(х) - обчислення модуля х (long x);

 

Примітка: Для обчислення абсолютної величини треба підключити бібліотеку математичних функцій math.h:

      #include <math.h>

 

      Приклад 1C.

 

#include <stdio.h>

 

/* Zmax */

main()

{

  unsigned j, k, n;

  int a, m;

 

  printf(n=? ); scanf(“%u”, &n);

  printf( 1-? ); scanf(“%d”, &m);

  k = 1;

  for (j=2; j<=n; j++)

   {

    printf(“%u-? “, j); scanf(“%d”, &a);

    if (a>m)

     {

      m = a; k = j;

     }

   }

  printf(“ Найбільше= %d Номер= %d\n”, m, k);

}

 

      Приклад 2C.

 

#include <stdio.h>

#include <math.h>

 

/* Euclid */

main()

{

  int x, y, m, n;

 

  printf(х, у=? ); scanf(“%d %d”, &x, &y);

  m = abs(x); n = abs(y);

  while (m!=n)

    if (m>n) m -= n;

    else n -= m;

  printf(НСД(%d,%d)= %d\n”, x, y, m);

  n = abs(x) / m;

  if (n>32767 / abs(y)) printf(Переповнення\n”);

  else printf(НСК(%d,%d)= %d\n”, x, y, n*abs(y));

}

 

5.3.3. Дійсний тип

 

      Мова Паскаль. Множина значень залежить від типу. Типи вказано у таблиці.

 

  Тип              Диапазон          Цифр мантиси  Байтів

  real      2.9e  -39 .. 1.7e  38      11-12         6

  single    1.5e  -45 .. 3.4e  38       7- 8         4

  double    5.0e -324 .. 1.7e 308      15-16         8

  extended  3.4e-4932 .. 1.1e4932      19-20        10

 

Приклади описів змінних:

      var X, Y, Z: real;

      var a, b, c: single;

      var s, p, q: double;

      var t, u, v: extended;

 

Значення констант записуються в форматі з фіксованою або плаваючою крапкою, наприклад, 0, 0.0 Е+00, 3.14159, 6.022 Е-13.

      Є зарезервована константа - число Pi=3.1415926536Е+00.

      Над елементами х, у дійсного типу визначені наступні:

 

      a) операції: додавання х+у; віднімання x-y; множення х*у; ділення х/у.

 

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

 

    b) функції:

       abs(х) - обчислення модуля х;

       sqr(х) - обчислення х2;

 

       sqrt(х) - обчислення квадратного кореня з х;

 

       sin(х) - обчислення синуса х;

 

       cos(х) - обчислення косинуса х;

 

       arctan(х) - обчислення арктангенса х;

 

       ln(х) - обчислення натурального логарифма від х;

 

       exp(х) - обчислення еx;

 

       frac(х) - обчислення дробової частини х, наприклад, frac(2.7) = 0.7;

 

       int(х) - округлення числа х шляхом відкидання дробової частини, наприклад, int(2.9) = 2.0, int(-2.9) = -2.0;

 

       random - генерація випадкового числа з діапазону [0,0.99].

 

      Ще дві функції trunc і round служать для перетворення дійсного числа х в ціле

 

       trunc(х) = sign(х)*[ ¦х¦ ];

       round(х) = sign(х)*[¦х¦+1/2 ].

 

      Приклад 3P. Обчислення суми

                 k

                 S  sin kn

            10  n=1

        S =  S  -----------.

            k=1      k!

 

    program Sum;

       var K, N: word;

           S, Т, U: real;

    begin

       S:= 0; U:= 1.0;

       for K:=1 to 10 do begin

          U:= U*K; Т:= 0;

          for N:=1 to K do

          Т:= Т+sin(K*N);

          S:= S+Т/U

       end;

       write(' Сума= ', S)

    end.

 

      Приклад 4P. Програма наближеного обчислення а1/n, яка використовує той факт, що

 

     1/n                      а+n-1

    а    =  lim  х ,    х  = -------,

           k->¥   k      1      2

              _                _

           1 ¦             а    ¦

    х    = - ¦(n-1)*х  + ------ ¦,  k=1,2,...

     k+1   n ¦       k     n-1  ¦

             ¦_           х   

                           k

для " а > 0 і n Î N.

      Складемо програму в якій обчислення проводяться до виконання умови ¦хk+1хk¦< e, де e>0.

 

    program Sq1;

       var N, K, M: integer;

           А, X, Y, Z, Eps: real;

    begin

       write('n, a, eps=? '); readln(N, А, Eps);

       M:= N-1; Y:= 0.0; X:= (А+M)/2.0; K:= 1;

       while abs(X-Y)>=Eps do begin

          Y:= X; Z:= exp(M*ln(X));

          X:= (M*Х+А/Z)/N; K:= K+1

       end;

       write(' Через ', K:1,' кроків ', А,' ^ 1/', N:1,' = ', X)

    end.

 

      При e=0.01 через 9 кроків отримали, що корінь п'ятої степені з числа 3.71293 приблизно рівний 1.3000003980 Е+00.

      Якщо обчислення провести до виконання умови ¦а – хkn¦ < e, з використанням програми

 

    program Sq2;

       var N, K, M: integer;

           А, X, Z, Eps: real;

    begin

       write('n, a, eps=? '); readln(N, А, Eps);

       M:= N-1; X:= (А+M)/2.0; Z:= exp(M*ln(X)); K:= 1;

       while abs(A-Z*Х)>=Eps do begin

          X:= (M*Х+А/Z)/N; K:= K+1;

          Z:= exp(M*ln(X))

       end;

       write(' Через ', K:1,' кроків ', А,' ^ 1/', N:1,' = ', X)

    end.

 

то через 8 ітерацій наближене значення кореня дорівнюе 1.3005088115Е+00.

      Вправа 5.1. Пояснити природу розходження в результатах розв’язку задачі, враховуючи, що при виконанні однієї і другої програми х7 = 1.3184430036Е+00.¦

 

      У мові Сі є три дійсні типи: float, double та long double. Диапазони значень, кількість цифр мантиси та кількість байтів для цих типів дорівнює відповідним значенням типів single, double та extended Паскаля.

 

      Над елементами х, у дійсного типу визначені наступні:

 

      a) операції: додавання х+у; віднімання x-y; множення х*у; ділення х/у.

 

    b) функції:

       fabs(х) - обчислення модуля х;

 

       sqrt(х) - обчислення квадратного кореня з х;

 

       sin(х) - обчислення синуса х;

 

       cos(х) - обчислення косинуса х;

 

       asin(х) - обчислення арксинуса х;

 

       acos(х) - обчислення арккосинуса х;

 

       atan(х) - обчислення арктангенса х;

 

       log(х) - обчислення натурального логарифма від х;

 

       log10(х) - обчислення десяткового логарифма від х;

 

       exp(х) - обчислення еx;

 

       pow(х,y) - обчислення xy;

 

       ceil(х) – найменше ціле число, більше або рівне x;

 

       floor(х) – найбільше ціле число, менше або рівне x;.

 

Примітка: Для обчислення абсолютної величини треба підключити бібліотеку математичних функцій math.h. Всі аргументи та результати функцій належать до типу double.

 

      Приклад 3C.

 

#include <stdio.h>

#include <math.h>

 

/* Sum */

main()

{

  unsigned k, n;

  double s, t, u;

 

  s = 0; u = 1.0;

  for (k=1; k<=10; k++)

    {

     u *= k; t = 0;

     for (n=1; n<=k; n++)

       t += sin(k*n);

     s += t/u;

    }

  printf( Сума= %lf”, s);

}

 

      Приклад 4C.

 

#include <stdio.h>

#include <math.h>

 

/* Sq1 */

main()

{

  int k, n, m;

  double a, x, y, z, eps;

 

  printf(n, a, eps=?);

  scanf(“%d %lf %lf”, &n, &a, &eps);

  m = n-1; y = 0.0; x = (a+m)/2.0; k = 1;

  while (fabs(x-y)>=eps)

    {

     y = x; z = exp(m*log(x));

     x = (m*x+a/z)/n; k++;

    }

  printf( Через %d кроків %lf ^ 1/%d = %lf”, k, a, n, x);

}

 

[ЗМІСТ]      [Далі]       [Назад]      [Початок розділу]