Можете ли да се доверите на резултатите от изчисленията с плаваща запетая

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

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

Ако например изчисленията, получени с единична и двойна точност, съвпадат, тогава се създава усещане за увереност в резултата, поне с точност, сравнима с единичната. Тук бих искал да дам един интересен пример, демонстриращ, че дори всравнително проста аритметична задача, такава стабилност с променлива точност на представяне на числа не може да служи като основа за такава увереност. Необходимо е да се изчисли стойността на функция от две променливи с определени стойности (посочени по-долу) на нейните аргументи:

Забелязах този пример, когато се занимавах с библиотеката C-XSC (система от клас C за (основно) произволни научни изчисления с интервал на точност). Тази библиотека е отлична за практическо изследване на изчислителната стабилност на различни числени алгоритми.

За да емулирате изчисления с плаваща запетая в Python, инсталирайте пакета mpmath. По принцип, ако се ограничим до точността на IEEE 754, NumPy също може да се използва, но трябва да покажем, че резултатите, получени съгласно IEEE 754, са неправилни.

Нека изчислим стойността на функциятаf(a,b) сa= 77617 иb= 33096.

Читателят може да забележи, че определянето на прецизност вdpsвmpmathне е съвсем правилният подход при емулиране на реална двойна прецизност. Ако говорим за двойна и / или единична точност в рамките на IEEE, тогава може би е по-правилно да опишем техните характеристики чрез двоичната система. Тук обаче това не е толкова важно; от друга страна, използването наmp.dpsсе тълкува по-лесно - т.е. като броя на десетичните значещи цифри в представянето на числото.

Изпълнявайки кода, получаваме:

Доста убедително, нали? Само стойността е грешна! Правилната стойност, даденаaиbобикновено е по-малка от единица!

Нека завършим примера със следните изчисления:

Получаваме (някои редове са пропуснати):

Вижда се, че въпреки стабилността, някои стойности все още се различават значително от обичайните, което вече ви кара да се замислите. Ще ви кажа веднага, получените стойности с точностdps=36и по-високи са верни. Но откъде знаете, че при по-нататъшно увеличаване на точността няма да има скок, защото, както се видя при стойност от 1.17260. дори стабилността на резултата при различна точност не може да гарантира неговата коректност.

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

Нека извършим изчисления с помощта на апарата за интервална аритметикаmpmath:

Интересно е да се проследи еволюцията на интервала от възможни стойности на функцията: тя се стабилизира само при използване на точност от 36 или повече значими десетични цифри, въпреки чеи постепенно се стеснява. От интервалните изчисления става съвсем ясно, че трябва да се вярва само на резултатите, получени с точност доdps=36или повече десетични цифри.

Този пример е ясна демонстрация колко внимателни трябва да бъдете, когато правите изчисления с плаваща запетая и че дори 128-битова точност (напримерnumpy.float128, когато говорим за Python и NumPy) може да се окаже недостатъчна. Това също така показва, че не може да се вярва на стабилността на резултата, получен при различни точности. Използването на апарата за интервални изчисления може да бъде едно от решенията в този случай, което ви позволява да оцените необходимата точност, за да получите адекватен резултат.

Hardcore conf в C++. Каним само професионалисти.