(Пълна) Ръководство за разбиране IEEE плаваща грешки

Отказ от отговорност за оттеглено съдържание на БЗ

Тази статия е написана за продукти, за които Microsoft вече не предлага поддръжка. Ето защо тази статия се предлага „както е“ и вече няма да бъде актуализирана.

Резюме

Плаваща математическа е сложна тема, която обърква много програма. Начинаещи по-долу да ви помогне да разпознава програмиране ситуации, където плаваща грешки могат да възникнат и как да ги избегнем. Той също трябва да накара да разпознава случаи, причинени от присъщи плаваща математически ограничения за разлика от действителните компилатор грешки.

Допълнителна информация

Десетичен и двоично число системи

Обикновено ние броя неща база 10. Базата е напълно произволно. Единствената причина, че хората по традиция са използвали база 10 е, че имат 10 пръста, които са удобни инструменти за отчитане.


Номера на 532.25 в десетична (с основа 10) са следните:

   (5 * 10^2) + (3 * 10^1) + (2 * 10^0) + (2 * 10^-1) + (5 * 10^-2)
500 + 30 + 2 + 2/10 + 5/100
_________
= 532.25


В двоична система (база 2) всяка колона представлява силата на 2 вместо 10. Например броят 101.01 означава следното:

   (1 * 2^2) + (0 * 2^1) + (1 * 2^0) + (0 * 2^-1) + (1 * 2^-2)
4 + 0 + 1 + 0 + 1/4
_________
= 5.25 Decimal


Как числа са представени в компютри

Тъй като не е частична част до цяло число, неговото представяне машина е много по-лесно, отколкото за плаваща запетая стойности. Нормално числа на персонални компютри са 2 байта (16 бита) с най-важните малко показва знак. Дълги числа са 4 байта. Положителни стойности са ясно двоични числа. Например:

    1 Decimal = 1 Binary
2 Decimal = 10 Binary
22 Decimal = 10110 Binary, etc.


Обаче отрицателна стойност са представени два допълнение схема. Да получите две допълнение представяне за отрицателно число, вземете двоичен номер абсолютна стойност и обърнете бита и добавяне на 1. Например:

   4 Decimal = 0000 0000 0000 0100
1111 1111 1111 1011 Flip the Bits
-4 = 1111 1111 1111 1100 Add 1


Имайте предвид, че -1 десетично = 1111 1111 1111 1111 двоични, което обяснява защо Basic третира -1 като логически true (всички бита = 1). Това е следствие на нямат отделни оператори побитови и логически сравнения. Често Basic, това е да използвате фрагмент код по-долу, когато програмата ще направи много логически сравнения. Това значително помага четливост.

   CONST TRUE = -1
CONST FALSE = NOT TRUE


Имайте предвид, че добавянето на комбинация от два допълват номера като обикновен двоична аритметика произвежда правилни резултати.

Плаваща усложнения

Всеки десетично число, може да представлява точно от двоично число; Това обаче не е вярно за частична номера. Всъщност всяко число, което е нерационално база 10 ще бъде ирационално в система с по-малка от 10 база.


За binary по-специално, само частична номера, които могат да бъдат представени във формата p/q, където q е число мощност от 2, може да се изрази точно с ограничен брой битове.


Дори често десетична части, като например десетична 0.0001, не може да представлява точно в двоичен. (0.0001 е повтаряща се двоична дроб с период от 104 бита!)


Това обяснява защо прост пример, като например

   SUM = 0
FOR I% = 1 TO 10000
SUM = SUM + 0.0001
NEXT I%
PRINT SUM ' Theoretically = 1.0.


ще печат 1.000054 като продукция. Малка грешка в представляващи 0.0001 в двоичен разпространява сума.


Същата причина винаги да много внимателни при сравнение на реални числа. Следният пример илюстрира обща програмна грешка:

   item1# = 69.82#
item2# = 69.20# + 0.62#
IF item1# = item2# then print "Equality!"


Това ще се ОТПЕЧАТВА "Равенство!" защото 69.82 не може да представлява точно в двоичен, което води до стойността, която е резултат от задачата да бъде различен (в двоичен) от стойността, която се генерира от израз. На практика трябва винаги да код такива сравнения по такъв начин, че за някои толеранс. Например:

   IF (item1# < 69.83#) AND (item1# > 69.81#) then print "Equal"


Това ще се ОТПЕЧАТА "Равно".

IEEE формат номера

QuickBasic за MS-DOS, версия 3.0 е изпратен с версия MBF (Microsoft двоично плаваща запетая) и IEEE (институт по електро- и електронен инженери) версия за машини с математически coprocessor. QuickBasic за MS-DOS, версии 4.0 и по-късно използвате IEEE. Microsoft избра стандарта IEEE да представите с плаваща запетая стойности в текущи версии на основния по следните три основни причини:

  1. За да позволите Basic да използва Intel математически coprocessors, които използват IEEE формат. Intel 80 x 87 серия coprocessors не може да работи с Microsoft двоичен формат номера.
  2. За да направите interlanguage професия между Basic, C, Паскал, НАУЧАВАНЕ и MASM много по-лесно. В противен случай преобразуване процедури би трябвало да се използва за изпращане на числени стойности от един език на друг.
  3. За постигане на съвместимост. IEEE е индустриален стандарт за C и НАУЧАВАНЕ компилатори.
По-долу е бърз сравнение на IEEE и MBF заявления за двойна точност номер:

               Sign Bits   Exponent Bits   Mantissa Bits
--------- ------------- -------------
IEEE 1 11 52 + 1 (Implied)
MBF 1 8 56


За повече информация относно разликите между IEEE и MBF плаваща представителство, търсене в базата знания на Microsoft на следния текст:

   IEEE and floating and point and appnote


Обърнете внимание, че IEEE повече битове, посветен на степен, която позволява да се представят по-широк диапазон от стойности. MBF има повече mantissa бита, което позволява по-точно в гамата тясна.

Общи понятия с плаваща запетая

Това е много важно да разберем, че всички двоични плаваща система може да представлява само ограничен брой с плаваща запетая стойности в точната форма. Всички други стойности трябва да се сближат по-близо изводим стойност. IEEE стандарт установява метод за закръгляване стойностите на "най-близо" изводим стойност. QuickBasic за MS-DOS поддържа стандарта и кръга по IEEE правила.


Също така имайте предвид, че цифрите, които могат да бъдат представени в IEEE са разпределени в много широк диапазон. Можете да ги представите на номер на ред. Има висока плътност изводим числа 1.0 и -1.0, но по-малко по-малко като да преминете към 0 или infinity.


Целта на стандарта IEEE, който е предназначен за инженерни изчисления, е да се увеличи точността (за да получите възможно най-скоро на номер). Точност е броят на цифрите, които могат да представляват. Стандарт IEEE се опитва да балансира броят на битовете за експонента с броя на битовете, използвани за дробна част от номера за точност и прецизност в допустими граници.

IEEE данни

Числа с плаваща запетая са представени в следната форма, където [експонента] е двоичен степен:

   X =  Fraction * 2^(exponent - bias)


[Част] е нормализирана дробна част от броя, нормализирани защото експонента се регулира така, че водещите бит е винаги 1. По този начин, тя трябва да се съхраняват и получавате една по-малко прецизност. Ето защо има подразбиращи се малко. Можете да мислите за това като плаваща, където манипулиране на експонента да има една цифра вляво от десетичния знак, освен в двоичен, винаги можете да обработвате степен, така че първия бит е 1, тъй като има само 1s и нули.


[отместване] е да не се налага да съхранявате отрицателни bias стойност.


Отместване за единична точност номера е 127 и 1023 (десетична) за двойна точност номера.


Стойностите равна на 0 и всички 1 (двоични) са запазени представляват специални случаи. Има и други специални случаи, които показват различни грешки условия.

Примери за единична точност

2 = 1 * 2 ^ 1 = 0100 0000 0000 0000... 0000 0000 = 4000 0000 hex
Отбележете бит за знак е нула, и съхранени експонента е 128 или 100 0000 0 в двоичен, който е 127 плюс 1. Съхраняваните mantissa е (1.) 000 0000... 0000 0000, който има водещи подразбиращи 1 и двоични точка, действителната mantissa е 1.

-2 = -1 * 2 ^ 1 = 1100 0000 0000 0000... 0000 0000 = C000 0000 hex
Също като 2 освен това бита за знак. Това важи за всички IEEE формат за числа с плаваща запетая.

4 = 1 * 2 ^ 2 = 0100 0000 1000 0000... 0000 шестнадесетичен 0000 = 4080 0000
Същата mantissa експонента се увеличава (предубедени стойност е 129 или 100 0000 1 в двоичен.

6 = 1.5 * 2 ^ 2 = 0100 0000 1100 0000... 0000 0000 = 40C 0 0000 hex
Същата степен, mantissa е по-голям от полу - (1.) 100 0000... 0000 0000, което, тъй като това е двоичен част 1-1/2 (стойностите на частична цифрите са 1/2, 1/4, 1/8, и т.н.).

1 = 1 * 2 ^ 0 = 0011 1111 1000 0000... 0000 шестнадесетичен 0000 = 3F80 0000
Същата степен като останалите правомощията на 2 mantissa е една по-малко от 2 127 или 011 1111 1 в двоичен.

.75 = 1.5 * 2 ^ -1 = 0011 1111 0100 0000... 0000 шестнадесетичен 0000 = 3F40 0000
Предубедени експонента е 126, 011 1111 0 в двоичен и mantissa е (1.) 100 0000... 0000 0000, който е 1-1/2.

2.5 = 1,25 * 2 ^ 1 = 0100 0000 0010 0000... 0000 шестнадесетичен 0000 = 4020 0000
Същата като 2 освен това нещо, което представлява 1/4 се намира в mantissa.

0,1 = 1.6 * 2 ^ -4 = 0011 1101 1100 1100... 1100 1101 = 3DCC CCCD hex
1.10 е повтарящ се част в двоичен. Mantissa е само притеснявайте на 1.6 и предубедени експонента казва, че 1.6 разделена 16 (е 011 1101 1 в двоичен, който е 123 в десетична). Налице експонента е 123-127 = - 4, което означава, че фактор от който да се умножава 2 ** -4 = 1/16. Имайте предвид, че съхраняваните mantissa е закръглен в последната малко. Това е опит да представлява невъзпроизводимото число възможно. (Причината, 1/10 и 1/100 точно representable в двоичен е подобен на начина, че 1/3 е точно representable в десетична.)

0 = 1.0 * 2 ^-128 = всички нули - специален случай.

Други често срещани грешки с плаваща запетая

Следват често срещани грешки с плаваща запетая:

  1. Кръг от грешка


    Тази грешка се получава, когато битове в двоичното число не могат да бъдат използвани при изчисление.


    Пример: Добавяне 0.0001 към 0.9900 (единична точност)


    Десетичен 0.0001 ще бъдат представени като:
    (1.) 10100011011011100010111 * 2^(-14+Bias) (13 водещи нули в двоичен!)
    0.9900 ще бъдат представени като:
    (1.)11111010111000010100011 * 2^(-1+Bias)
    Сега да повишат тези цифри, трябва да е насочен десетична (двоични) точки. Това трябва да бъде Unnormalized. Ето резултат добавка:
           .000000000000011010001101 * 2^0  <- Only 11 of 23 Bits retained
    +.111111010111000010100011 * 2^0
    ________________________________
    .111111010111011100110000 * 2^0


    Това се нарича кръг от грешка, защото някои компютри кръг при изместване на добавка. Други просто отрежете. Кръг от грешки са важни, за да имате предвид, когато добавяте или умножава две различни стойности.
  2. Изваждане на две почти равни стойности
           .1235
    -.1234
    _____
    .0001


    Това ще бъде нормализирано. Имайте предвид, че въпреки първоначалния номера четири цифри, резултатът само един значими цифри.
  3. Препълване и отрицателно препълване


    Това се случва, когато резултатът е твърде голяма или твърде малка да бъде представен от типа на данните.
  4. Quantizing грешка


    Това се случва с тези цифри, които не могат да бъдат представени в точната форма с плаваща стандарт.
  5. Деление на много малък брой


    Това може да предизвика "деление на нула" грешка или може да доведе до лоши резултати, както в следния пример:
          A = 112000000
    B = 100000
    C = 0.0009
    X = A - B / C


    В QuickBasic за MS-DOS X сега има стойност 888887, вместо правилния отговор, 900000.
  6. Изходна грешка


    Този тип грешка възниква, когато функциите на изхода променя стойностите, които работят.
Свойства

ИД на статията: 42980 – Последен преглед: 16.01.2017 г. – Редакция: 1

Обратна връзка