Python, широко поширена мова програмування, відмінно справляється з чисельними обчислювальними завданнями, але вона не застрахована від проблем, пов’язаних з арифметикою з плаваючою комою. Числа з плаваючою комою в Python є наближеннями дійсних чисел, що призводить до помилки округлення, втрата точності та скасування що може порушити розрахунки. Ми можемо виявити ці помилки, шукаючи дивні результати і за допомогою інструментівnumpy.finfo>до точність моніторингу . З певною обережністю та хитрими трюками ми можемо тримайте ці помилки під контролем і переконайтеся, що наші обчислення Python надійні. У цій статті ми дослідимо тонкощі помилок із плаваючою комою Python .
Що таке числа з плаваючою комою?
Числа з плаваючою комою є ефективним способом представлення дійсних чисел у комп’ютерах. Вони складаються з трьох частин:
- Значні: Фактичні цифри, що представляють число (наприклад, 3,14159)
- Експонента: Повідомляє, на скільки місць потрібно зсунути значуще вліво або вправо (наприклад, -2 у 3,14159 x 10^-2)
- база: Зазвичай 2 для комп’ютерів, що визначає, як числа представлені всередині
Чому виникають помилки з плаваючою комою?
Помилки з плаваючою комою виникають через те, що комп’ютери зберігають дійсні числа, використовуючи кінцеву кількість бітів, що призводить до наближень і потенційних неточностей. Числа з плаваючою комою мають внутрішні обмеження:
- Кінцева точність: Лише обмежена кількість цифр може зберігатися в значущому, що веде до помилки округлення при поданні точних десяткових дробів.
- Втрата точності: Такі операції, як додавання чи віднімання, можуть ще більше знизити точність, посилюючи ефект округлення.
- Нижній/переливний: Надзвичайно малі чи великі числа можуть виходити за межі репрезентованого діапазону, що призводить до недоплив (стає нульовим) або перелив (стає нескінченністю).
Типи помилок із плаваючою комою
а) Помилки округлення: Найпоширеніший, коли необхідно наблизити точне десяткове число, щоб відповідати обмеженій точності числа з плаваючою точкою.
b) Втрата точності: Подальші операції можуть поступово накопичувати помилки округлення, що призводить до значних неточностей кінцевого результату.
c) Катастрофічне скасування: Під час віднімання майже рівних чисел із протилежними знаками їхні значущі цифри компенсуються, залишаючи маленький і неточний результат.
додавання рядка в java
d) переповнення/переповнення: Це відбувається, коли обчислення виходять за межі репрезентованого діапазону плаваючих значень, що призводить до неточних або безглуздих результатів.
Виявлення помилок із плаваючою комою
- Спостереження за неочікуваними результатами: Порівняння обчислених значень із очікуваними результатами або візуалізація даних може виявити невідповідності, які часто викликані помилками.
- Використання таких бібліотек, як
numpy.finfo>: Бібліотеки люблятьnumpy>надати такі інструменти, якfinfo>щоб перевірити точність і обмеження різних типів даних float.
Помилка з плаваючою комою Python
Тут ми обговоримо різні типи прикладів, які ілюструють помилки з плаваючою комою в Python:
Втрата точності при перетворенні десяткової системи в двійкову
У цьому прикладі десяткове число 0,1 перетворюється на двійкове. Через нескінченне двійкове розширення 0,1 використовується лише кінцева кількість бітів, що призводить до втрати точності.
Python3
decimal_number>=> 0.1> binary_representation>=> format>(decimal_number,>'.30f'>)># 30 decimal places> print>(f>'Decimal: {decimal_number}
Binary: {binary_representation}'>)> |
>
>
Вихід:
Decimal: 0.1 Binary: 0.100000000000000005551115123126>
Помилки округлення
Тут результат додавання 1/3 три рази очікується як 1,0. Однак через помилки округлення при представленні 1/3 сума може бути неточною 1,0.
Python3
result>=> 1.0> /> 3.0> sum_result>=> result>+> result>+> result> print>(f>'Expected Result: 1.0
Actual Result: {sum_result}'>)> |
>
>
Вихід:
Expected Result: 1.0 Actual Result: 1.0>
Накопичувальні помилки в ітераційних обчисленнях
Цей приклад демонструє, як можуть виникнути накопичувальні помилки в ітеративних обчисленнях. Додавання 0,1 десять разів може не дати точного результату 1,0 через обмеження точності числа з плаваючою комою.
Python3
total>=> 0.0> for> i>in> range>(>10>):> >total>+>=> 0.1> print>(f>'Expected Result: 1.0
Actual Result: {total}'>)> |
ymail
>
>
Вихід:
Expected Result: 1.0 Actual Result: 0.9999999999999999>
Проблеми порівняння
У цьому випадку порівняння суми 0,1 і 0,2 з 0,3 може не дати очікуваногоTrue>результат через притаманну неточність чисел з плаваючою комою.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Вихід:
a: 0.30000000000000004 b: 0.3 Equal: False>
Несподівані результати в розрахунках
Тут віднімання1e16>від суми(1e16 + 1)>Очікується, що дасть 1, але через помилки з плаваючою комою результат може бути не точно 1.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Вихід:
Expected Result: 1 Actual Result: 0.0>
Розуміння точності з плаваючою комою
Тут ми розберемося з точністю з плаваючою комою: Аномалія 1.2 – 1.0 у Python-
Виклики представництва
Як відомо, 1,2 – 1,0 = 0,2. Але коли ви спробуєте зробити те саме в Python, ви будете здивовані результатами:
>>> 1,2 - 1,0>>
Вихід:
0.199999999999999996>
Це можна вважати помилкою в Python, але це не так. Це має мало спільного з Python і набагато більше пов’язано з тим, як базова платформа обробляє числа з плаваючою комою. Це нормальний випадок, який виникає під час внутрішньої обробки чисел з плаваючою комою в системі. Це проблема, спричинена внутрішнім представленням чисел з плаваючою комою, яке використовує фіксовану кількість двійкових цифр для представлення десяткового числа. Важко представити деякі десяткові числа в двійковій системі, тому в багатьох випадках це призводить до невеликих помилок округлення. Ми знаємо подібні випадки в десятковій математиці, багато результатів не можна представити фіксованою кількістю десяткових цифр, оскільки приклад
10 / 3 = 3.33333333.......>
У цьому випадку, беручи 1.2 як приклад, подання 0.2 у двійковому вигляді буде 0.00110011001100110011001100…… і так далі. Це нескінченне десяткове число важко зберігати всередині. Зазвичай значення об’єкта з плаваючою комою зберігається у двійковій формі з плаваючою комою з фіксованою точністю ( зазвичай 53 біти ). Тож представляємо 1.2 внутрішньо як,
1.0011001100110011001100110011001100110011001100110011>
Що точно дорівнює:
1.1999999999999999555910790149937383830547332763671875>
Обробка помилки з плаваючою комою
Тут ми обговоримо різні приклади обробки помилок із плаваючою комою в Python:
рядок java для char
Округлення до певного десяткового знака
Округливши результат до певного десяткового знаку (наприклад, 2), ви можете пом’якшити вплив невеликих помилок із плаваючою комою.
Python3
result>=> 1.2> -> 1.0> rounded_result>=> round>(result,>2>)> print>(f>'Original Result: {result}
Rounded Result: {rounded_result}'>)> |
>
>
Вихід:
Original Result: 0.19999999999999996 Rounded Result: 0.2>
Використання десяткового класу для високої точності
Thedecimal>модуль забезпечуєDecimal>класу, що забезпечує більш точну арифметику. Встановлення точності зgetcontext().prec>може допомогти в управлінні точністю для конкретних обчислень
Python3
from> decimal>import> Decimal, getcontext> getcontext().prec>=> 4> # Set precision to 4 decimal places> result>=> Decimal(>'1.2'>)>-> Decimal(>'1.0'>)> print>(f>'High Precision Result: {result}'>)> |
>
>
Вихід:
High Precision Result: 0.2>
Використання дробів для точних представлень
Thefractions>модуль дозволяє працювати з точними дробовими представленнями, уникаючи помилок з плаваючою комою.
Python3
from> fractions>import> Fraction> result>=> Fraction(>'1.2'>)>-> Fraction(>'1.0'>)> print>(f>'Exact Fractional Result: {result}'>)> |
>
concat рядки java
>
Вихід:
Exact Fractional Result: 1/5>
Обробка проміжних результатів за допомогою десяткового числа
ВикористовуватиDecimal>клас для проміжних обчислень, щоб мінімізувати сукупні помилки перед перетворенням назад у float.
Python3
from> decimal>import> Decimal, getcontext> getcontext().prec>=> 6> # Set precision to 6 decimal places> intermediate_result>=> Decimal(>'1.2'>)>-> Decimal(>'1.0'>)> final_result>=> float>(intermediate_result)># Convert back to float if needed> print>(f>'Intermediate Result: {intermediate_result}
Final Result: {final_result}'>)> |
>
>
Вихід:
Intermediate Result: 0.2 Final Result: 0.2>
Висновок
Ви все одно думаєте чому python не вирішує цю проблему , насправді це не має нічого спільного з python. Це відбувається тому, що базова платформа c обробляє числа з плаваючою комою, і, зрештою, через неточність ми завжди будемо записувати числа у вигляді рядка з фіксованою кількістю цифр. Зауважте, що це в самій природі двійкового числа з плаваючою комою: це також не є помилкою Python або C , і це також не помилка у вашому коді. Ви побачите однакову поведінку в усіх мовах, які підтримують арифметику з плаваючою комою нашого обладнання, хоча деякі мови можуть не відображати різницю за замовчуванням або в усіх режимах виводу). Ми повинні враховувати цю поведінку, коли ми дбаємо про математичні задачі, які потребують точної точності, або використовуємо це в умовних операторах. Перевірте з плаваючою комою у розділі документації python для більшої кількості подібних дій.
Часті запитання (FAQ)
1. Що таке помилка з плаваючою комою в Python?
Помилка з плаваючою комою в Python стосується розбіжностей між очікуваними та фактичними результатами під час роботи з числами з плаваючою комою, що виникає через обмеження представлення дійсних чисел у двійковій системі.
2. Чому 1.2 - 1.0> не рівні 0.2> на Python?
Розбіжність пов’язана з властивими проблемами представлення десяткових чисел у двійковій системі. Під час внутрішнього двійкового представлення виникають помилки округлення, що призводить до неочікуваних результатів.
3. Чи є помилка з плаваючою комою помилкою в Python?
Ні, це не помилка в Python. Це поширена проблема в обчисленнях, пов’язана з внутрішнім представленням чисел з плаваючою комою. Python дотримується стандарту IEEE 754 для арифметики з плаваючою комою.
4. Як я можу округлити результат із плаваючою комою до певного десяткового знаку?
Ви можете використовувати
round()>функція округлення результату з плаваючою комою до певного десяткового знаку. Наприклад,rounded_result = round(result, 2)>.
5. Що decimal> і як він допомагає обробляти помилки з плаваючою комою?
The
decimal>модуль забезпечуєDecimal>клас для вищої точності арифметики. Встановлення точності та використанняDecimal>може допомогти зменшити помилки з плаваючою комою.