Python, široko používaný programovací jazyk, vyniká v úlohách numerických výpočtov, no nie je imúnny voči výzvam, ktoré predstavuje aritmetika s pohyblivou rádovou čiarkou. Čísla s pohyblivou rádovou čiarkou v Pythone sú aproximáciou reálnych čísel, čo vedie k chyby zaokrúhľovania, strata presnosti a zrušenia čo môže zhodiť výpočty. Môžeme odhaliť tieto chyby hľadaním zvláštnych výsledkov a pomocou nástrojovnumpy.finfo>do presnosť monitora . S určitou opatrnosťou a šikovnými trikmi to dokážeme majte tieto chyby pod kontrolou a uistite sa, že naše výpočty v Pythone sú spoľahlivé. V tomto článku preskúmame zložitosť chýb s pohyblivou rádovou čiarkou Python .
Čo sú to čísla s pohyblivou rádovou čiarkou?
Čísla s pohyblivou rádovou čiarkou sú efektívnym spôsobom reprezentácie reálnych čísel v počítačoch. Pozostávajú z troch častí:
- významné: Skutočné číslice predstavujúce číslo (napr. 3,14159)
- Exponent: Udáva, o koľko miest sa má posunúť significand doľava alebo doprava (napr. -2 v 3,14159 x 10^-2)
- základňa: Typicky 2 pre počítače, určujúce, ako sú čísla interne reprezentované
Prečo sa vyskytujú chyby s pohyblivou rádovou čiarkou?
Chyby s pohyblivou rádovou čiarkou vznikajú, pretože počítače ukladajú reálne čísla pomocou konečného počtu bitov, čo vedie k aproximáciám a potenciálnym nepresnostiam. Čísla s pohyblivou rádovou čiarkou majú vnútorné obmedzenia:
- Konečná presnosť: V significand je možné uložiť len obmedzený počet číslic, čo vedie k chyby zaokrúhľovania pri vyjadrení presných desatinných miest.
- Strata presnosti: Operácie, ako je sčítanie alebo odčítanie, môžu ďalej znížiť presnosť a znásobiť účinky zaokrúhľovania.
- Podtečenie/pretečenie: Extrémne malé alebo veľké čísla môžu spadať mimo reprezentovateľný rozsah, čo vedie k podtekanie (stane sa nulou) resp pretečeniu (stane sa nekonečnom).
Typy chýb s pohyblivou rádovou čiarkou
a) Chyby pri zaokrúhľovaní: Najčastejšie sa vyskytuje, keď je potrebné aproximovať presné desatinné číslo, aby vyhovovalo obmedzenej presnosti plaváka.
b) Strata presnosti: Následné operácie môžu postupne hromadiť chyby zaokrúhľovania, čo vedie k výrazným nepresnostiam v konečnom výsledku.
c) Katastrofické zrušenie: Pri odčítaní takmer rovnakých čísel s opačnými znamienkami sa ich platné číslice vyrušia, čím zostane malý a nepresný výsledok.
d) Pretečenie/Podtečenie: K tomu dochádza, keď výpočty prekračujú reprezentovateľný rozsah pohyblivých hodnôt, čo vedie k nepresným alebo nezmyselným výsledkom.
Detekcia chýb s pohyblivou rádovou čiarkou
- Pozorovanie neočakávaných výsledkov: Porovnanie vypočítaných hodnôt s očakávanými výsledkami alebo vizualizácia údajov môže odhaliť nezrovnalosti často spôsobené chybami.
- Používanie knižníc ako
numpy.finfo>: Knižnice akonumpy>poskytnúť nástroje akofinfo>na kontrolu presnosti a obmedzení rôznych typov údajov typu float.
Chyba s plávajúcou desatinnou čiarkou v Pythone
Tu budeme diskutovať o rôznych typoch príkladov, ktoré ilustrujú chyby s pohyblivou rádovou čiarkou v Pythone:
Strata presnosti pri prevode z desatinných miest na binárne
V tomto príklade sa desiatkové číslo 0,1 skonvertuje na binárne. V dôsledku nekonečného binárneho rozšírenia 0,1 sa používa iba konečný počet bitov, čo vedie k strate presnosti.
Python3
decimal_number>=> 0.1> binary_representation>=> format>(decimal_number,>'.30f'>)># 30 decimal places> print>(f>'Decimal: {decimal_number}
Binary: {binary_representation}'>)> |
>
>
Výkon:
Decimal: 0.1 Binary: 0.100000000000000005551115123126>
Chyby zaokrúhľovania
Tu sa očakáva, že výsledok pridania 1/3 trikrát bude 1,0. Kvôli chybám zaokrúhľovania pri vyjadrení 1/3 však súčet nemusí byť presne 1,0.
strojopis foreach
Python3
result>=> 1.0> /> 3.0> sum_result>=> result>+> result>+> result> print>(f>'Expected Result: 1.0
Actual Result: {sum_result}'>)> |
>
>
Výkon:
Expected Result: 1.0 Actual Result: 1.0>
Kumulatívne chyby v iteračných výpočtoch
Tento príklad ukazuje, ako sa môžu vyskytnúť kumulatívne chyby v iteračných výpočtoch. Pridanie 0,1 desaťkrát nemusí priniesť presný výsledok 1,0 kvôli obmedzeniam presnosti s pohyblivou rádovou čiarkou.
Python3
total>=> 0.0> for> i>in> range>(>10>):> >total>+>=> 0.1> print>(f>'Expected Result: 1.0
Actual Result: {total}'>)> |
>
>
Výkon:
Expected Result: 1.0 Actual Result: 0.9999999999999999>
Problémy porovnania
V tomto prípade porovnanie súčtu 0,1 a 0,2 až 0,3 nemusí priniesť očakávanýTrue>výsledkom je prirodzená nepresnosť čísel s pohyblivou rádovou čiarkou.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Výkon:
a: 0.30000000000000004 b: 0.3 Equal: False>
Neočakávané výsledky vo výpočtoch
Tu je odčítanie1e16>zo sumy(1e16 + 1)>očakáva sa, že prinesie 1, ale v dôsledku chýb s pohyblivou rádovou čiarkou nemusí byť výsledok presne 1.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
ankita dave
Výkon:
Expected Result: 1 Actual Result: 0.0>
Pochopenie presnosti s pohyblivou rádovou čiarkou
Tu pochopíme presnosť s pohyblivou rádovou čiarkou: Anomália 1,2 – 1,0 v Pythone-
Reprezentačné výzvy
Ako je známe, 1,2 – 1,0 = 0,2. Ale keď sa pokúsite urobiť to isté v Pythone, budete prekvapení výsledkami:
>>> 1,2 – 1,0>
Výkon:
0.199999999999999996>
Toto možno považovať za chybu v Pythone, ale nie je to tak. To má málo spoločného s Pythonom a oveľa viac s tým, ako základná platforma spracováva čísla s pohyblivou rádovou čiarkou. Ide o bežný prípad, ktorý sa vyskytuje pri internom spracovaní čísel s pohyblivou rádovou čiarkou v systéme. Je to problém spôsobený internou reprezentáciou čísel s pohyblivou rádovou čiarkou, ktorá používa pevný počet binárnych číslic na vyjadrenie desiatkového čísla. Je ťažké reprezentovať niektoré desatinné čísla v binárnom systéme, takže v mnohých prípadoch to vedie k malým chybám zaokrúhľovania. Poznáme podobné prípady v desiatkovej matematike, mnohé výsledky nemožno reprezentovať pevným počtom desatinných číslic, napr. Príklad
10 / 3 = 3.33333333.......>
V tomto prípade, ak vezmeme ako príklad 1,2, reprezentácia 0,2 v binárnej podobe je 0,00110011001100110011001100…… a tak ďalej. Je ťažké interne uložiť toto nekonečné desatinné číslo. Normálne je hodnota objektu float uložená v binárnej pohyblivej rádovej čiarke s pevnou presnosťou ( zvyčajne 53 bitov ). Takže zastupujeme 1.2 vnútorne ako,
1.0011001100110011001100110011001100110011001100110011>
Čo sa presne rovná:
1.1999999999999999555910790149937383830547332763671875>
Manipulácia s chybou s pohyblivou rádovou čiarkou
Tu budeme diskutovať o rôznych príkladoch, ako zvládnuť chyby s pohyblivou rádovou čiarkou v Pythone:
Zaokrúhľovanie na konkrétne desatinné miesto
Zaokrúhlením výsledku na konkrétne desatinné miesto (napr. 2) môžete zmierniť vplyv malých chýb s pohyblivou rádovou čiarkou.
Python3
result>=> 1.2> -> 1.0> rounded_result>=> round>(result,>2>)> print>(f>'Original Result: {result}
Rounded Result: {rounded_result}'>)> |
>
>
Výkon:
Original Result: 0.19999999999999996 Rounded Result: 0.2>
Použitie desatinnej triedy pre vysokú presnosť
Thedecimal>modul poskytujeDecimal>triedy, čo umožňuje vyššiu presnosť aritmetiky. Nastavenie presnosti pomocougetcontext().prec>môže pomôcť pri riadení presnosti pre špecifické výpočty
Python3
javascript pre rozbaľovaciu ponuku
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}'>)> |
>
>
Výkon:
High Precision Result: 0.2>
Použitie zlomkov na presné vyjadrenia
Thefractions>modul umožňuje prácu s presnými zlomkovými reprezentáciami, čím sa vyhýba chybám s pohyblivou rádovou čiarkou.
Python3
from> fractions>import> Fraction> result>=> Fraction(>'1.2'>)>-> Fraction(>'1.0'>)> print>(f>'Exact Fractional Result: {result}'>)> |
>
>
Výkon:
Exact Fractional Result: 1/5>
Spracovanie medzivýsledkov s desatinnou čiarkou
PoužiDecimal>triedy pre prechodné výpočty, aby sa minimalizovali kumulatívne chyby pred konverziou späť na 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}'>)> |
>
>
Výkon:
Intermediate Result: 0.2 Final Result: 0.2>
Záver
Napriek tomu rozmýšľaš prečo python tento problém nerieši , v skutočnosti to nemá nič spoločné s pythonom. Stáva sa to preto, že je to spôsob, akým základná platforma c spracováva čísla s pohyblivou rádovou čiarkou a nakoniec s nepresnosťou budeme vždy zapisovať čísla ako reťazec pevného počtu číslic. Všimnite si, že je to v samotnej podstate binárnej pohyblivej rádovej čiarky: ani to nie je chyba Python alebo C a nie je to chyba ani vo vašom kóde. Rovnaký druh správania uvidíte vo všetkých jazykoch, ktoré podporujú aritmetiku nášho hardvéru s pohyblivou rádovou čiarkou, hoci niektoré jazyky nemusia zobrazovať rozdiel v predvolenom nastavení alebo vo všetkých výstupných režimoch). Toto správanie musíme zvážiť, keď sa staráme o matematické problémy s požiadavkami na presnú presnosť alebo ich používame v podmienených príkazoch. Skontrolujte s pohyblivou rádovou čiarkou sekcia v dokumentácii pythonu, kde nájdete viac takýchto správaní.
Často kladené otázky (FAQ)
1. Čo je chyba s pohyblivou rádovou čiarkou v Pythone?
Chyba s pohyblivou rádovou čiarkou v Pythone sa týka nezrovnalostí medzi očakávanými a skutočnými výsledkami pri práci s číslami s pohyblivou rádovou čiarkou, ktoré vyplývajú z obmedzení reprezentácie reálnych čísel v binárnom systéme.
2. Prečo 1.2 - 1.0> nerovná sa 0.2> v Pythone?
Tento nesúlad je spôsobený inherentnými problémami pri reprezentácii desatinných čísel v binárnom systéme. Počas internej binárnej reprezentácie sa vyskytujú chyby zaokrúhľovania, čo vedie k neočakávaným výsledkom.
3. Je chyba s pohyblivou rádovou čiarkou chybou v Pythone?
Nie, nie je to chyba v Pythone. Je to bežný problém vo výpočtovej technike súvisiaci s tým, ako sú interne reprezentované čísla s pohyblivou rádovou čiarkou. Python dodržiava štandard IEEE 754 pre aritmetiku s pohyblivou rádovou čiarkou.
4. Ako môžem zaokrúhliť výsledok s pohyblivou rádovou čiarkou na konkrétne desatinné miesto?
Môžete použiť
round()>funkcia na zaokrúhlenie výsledku s pohyblivou rádovou čiarkou na konkrétne desatinné miesto. Napríklad,rounded_result = round(result, 2)>.
5. Čo je decimal> modul a ako pomáha zvládnuť chyby s pohyblivou rádovou čiarkou?
The
decimal>modul poskytujeDecimal>triedy pre vyššiu presnosť aritmetiky. Nastavenie presnosti a použitiaDecimal>môže pomôcť zmierniť chyby s pohyblivou rádovou čiarkou.