Python, široce používaný programovací jazyk, vyniká v numerických počítačových úlohách, přesto není imunní vůči výzvám, které představuje aritmetika s plovoucí desetinnou čárkou. Čísla s plovoucí desetinnou čárkou v Pythonu jsou aproximace reálných čísel, což vede k zaokrouhlovací chyby, ztráta přesnosti a zrušení to může shodit výpočty. Můžeme odhalit tyto chyby hledáním podivných výsledků a pomocí nástrojůnumpy.finfo>na sledovat přesnost . S trochou opatrnosti a chytrými triky to dokážeme udržet tyto chyby pod kontrolou a zajistit, aby naše výpočty v Pythonu byly spolehlivé. V tomto článku prozkoumáme složitosti chyb s plovoucí desetinnou čárkou Krajta .
Co jsou čísla s pohyblivou řádovou čárkou?
Čísla s plovoucí desetinnou čárkou jsou efektivním způsobem reprezentace reálných čísel v počítačích. Skládají se ze tří částí:
- Významný: Skutečné číslice představující číslo (např. 3,14159)
- Exponent: Udává, o kolik míst se má posunout significand doleva nebo doprava (např. -2 v 3,14159 x 10^-2)
- Základna: Typicky 2 pro počítače, určující, jak jsou čísla interně reprezentována
Proč dochází k chybám s plovoucí desetinnou čárkou?
Chyby s pohyblivou řádovou čárkou vznikají, protože počítače ukládají reálná čísla pomocí konečného počtu bitů, což vede k aproximacím a potenciálním nepřesnostem. Čísla s plovoucí desetinnou čárkou mají vnitřní omezení:
- Konečná přesnost: V significand lze uložit pouze omezený počet číslic, což vede k zaokrouhlovací chyby při reprezentaci přesných desetinných míst.
- Ztráta přesnosti: Operace, jako je sčítání nebo odečítání, mohou dále snížit přesnost a zhoršit účinky zaokrouhlování.
- Podtečení/přetečení: Extrémně malá nebo velká čísla mohou spadat mimo reprezentovatelný rozsah, což vede k podtékání (stane se nulou) nebo přetékat (stane se nekonečnem).
Typy chyb s pohyblivou řádovou čárkou
a) Chyby při zaokrouhlování: Nejčastěji se vyskytuje, když je třeba aproximovat přesné desetinné číslo, aby odpovídalo omezené přesnosti plováku.
b) Ztráta přesnosti: Následné operace mohou postupně hromadit chyby zaokrouhlování, což vede ke značným nepřesnostem v konečném výsledku.
c) Katastrofické zrušení: Při odečítání téměř stejných čísel s opačnými znaménky se jejich platné číslice vyruší, takže výsledek bude malý a nepřesný.
d) Přetečení/Podtečení: K tomu dochází, když výpočty překročí reprezentativní rozsah plovoucích hodnot, což vede k nepřesným nebo nesmyslným výsledkům.
Detekce chyb s pohyblivou řádovou čárkou
- Pozorování neočekávaných výsledků: Porovnání vypočtených hodnot s očekávanými výsledky nebo vizualizace dat může odhalit nekonzistence často způsobené chybami.
- Pomocí knihoven jako
numpy.finfo>: Knihovny jakonumpy>poskytnout nástroje jakofinfo>zkontrolovat přesnost a omezení různých typů dat float.
Chyba s plovoucí desetinnou čárkou v Pythonu
Zde budeme diskutovat o různých typech příkladů, které ilustrují chyby s plovoucí desetinnou čárkou v Pythonu:
Ztráta přesnosti při převodu desítkové soustavy na binární
V tomto příkladu je desetinné číslo 0,1 převedeno na binární. Kvůli nekonečné binární expanzi 0,1 je použit pouze konečný počet bitů, což vede ke ztrátě přesnosti.
Python3
bash jinak pokud
decimal_number>=> 0.1> binary_representation>=> format>(decimal_number,>'.30f'>)># 30 decimal places> print>(f>'Decimal: {decimal_number}
Binary: {binary_representation}'>)> |
>
>
Výstup:
Decimal: 0.1 Binary: 0.100000000000000005551115123126>
Zaokrouhlovací chyby
Zde se očekává, že výsledek přidání 1/3 třikrát bude 1,0. Kvůli chybám při zaokrouhlování při vyjádření 1/3 však součet nemusí být přesně 1,0.
Python3
result>=> 1.0> /> 3.0> sum_result>=> result>+> result>+> result> print>(f>'Expected Result: 1.0
Actual Result: {sum_result}'>)> |
>
>
Výstup:
Expected Result: 1.0 Actual Result: 1.0>
Kumulativní chyby v iterativních výpočtech
Tento příklad ukazuje, jak může v iterativních výpočtech docházet ke kumulativním chybám. Desetinásobné přidání 0,1 nemusí přinést přesný výsledek 1,0 kvůli omezení přesnosti s plovoucí desetinnou čárkou.
Python3
total>=> 0.0> for> i>in> range>(>10>):> >total>+>=> 0.1> print>(f>'Expected Result: 1.0
Actual Result: {total}'>)> |
>
>
Výstup:
Expected Result: 1.0 Actual Result: 0.9999999999999999>
Problémy se srovnáním
V tomto případě nemusí srovnání součtu 0,1 a 0,2 až 0,3 přinést očekávanýTrue>výsledek kvůli přirozené nepřesnosti čísel s plovoucí desetinnou čárkou.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Výstup:
a: 0.30000000000000004 b: 0.3 Equal: False>
Neočekávané výsledky ve výpočtech
Zde odečítání1e16>ze sumy(1e16 + 1)>očekává se, že dá 1, ale kvůli chybám s plovoucí desetinnou čárkou nemusí být výsledek přesně 1.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Výstup:
Expected Result: 1 Actual Result: 0.0>
Pochopení přesnosti s plovoucí desetinnou čárkou
Zde pochopíme přesnost s plovoucí desetinnou čárkou: Anomálie 1,2 – 1,0 v Pythonu-
Reprezentační výzvy
Jak je známo, 1,2 – 1,0 = 0,2. Ale když se pokusíte udělat totéž v Pythonu, budete překvapeni výsledky:
>>> 1,2 – 1,0>
Výstup:
0.199999999999999996>
To lze považovat za chybu v Pythonu, ale není. To má málo společného s Pythonem a mnohem více s tím, jak základní platforma zpracovává čísla s plovoucí desetinnou čárkou. Je to normální případ, se kterým se setkáváme při interním zpracování čísel s plovoucí desetinnou čárkou v systému. Je to problém způsobený vnitřní reprezentací čísel s plovoucí desetinnou čárkou, která používá pevný počet binárních číslic k reprezentaci desetinného čísla. Je obtížné reprezentovat některá desetinná čísla binárně, takže v mnoha případech to vede k malým zaokrouhlovacím chybám. Známe podobné případy v desítkové matematice, mnoho výsledků nelze reprezentovat pevným počtem desetinných číslic, např. Příklad
10 / 3 = 3.33333333.......>
V tomto případě, vezmeme-li jako příklad 1,2, reprezentace 0,2 v binární podobě je 0,00110011001100110011001100…… a tak dále. Je obtížné interně uložit toto nekonečné desetinné číslo. Normálně je hodnota objektu float uložena v binární pohyblivé řádové čárce s pevnou přesností ( obvykle 53 bitů ). Takže zastupujeme 1.2 vnitřně jako,
1.0011001100110011001100110011001100110011001100110011>
Což se přesně rovná:
1.1999999999999999555910790149937383830547332763671875>
Manipulace s chybou s plovoucí desetinnou čárkou
Zde budeme diskutovat o jiném příkladu, jak zacházet s chybami s plovoucí desetinnou čárkou v Pythonu:
Zaokrouhlování na konkrétní desetinné místo
Zaokrouhlením výsledku na konkrétní desetinné místo (např. 2) můžete zmírnit dopad malých chyb s plovoucí desetinnou čárkou.
Python3
result>=> 1.2> -> 1.0> rounded_result>=> round>(result,>2>)> print>(f>'Original Result: {result}
Rounded Result: {rounded_result}'>)> |
>
>
Výstup:
Original Result: 0.19999999999999996 Rounded Result: 0.2>
Použití desítkové třídy pro vysokou přesnost
Thedecimal>modul poskytujeDecimal>třídy, což umožňuje vyšší přesnost aritmetiky. Nastavení přesnosti pomocígetcontext().prec>může pomoci při správě přesnosti pro konkrétní výpočty
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}'>)> |
>
>
Výstup:
High Precision Result: 0.2>
Použití zlomků pro přesné vyjádření
Thefractions>modul umožňuje pracovat s přesnými zlomkovými reprezentacemi a vyhnout se chybám s plovoucí desetinnou čárkou.
Python3
from> fractions>import> Fraction> result>=> Fraction(>'1.2'>)>-> Fraction(>'1.0'>)> print>(f>'Exact Fractional Result: {result}'>)> |
>
>
Výstup:
Exact Fractional Result: 1/5>
Zpracování mezivýsledků s desetinnými místy
PoužijteDecimal>třídy pro mezivýpočty, aby se minimalizovaly kumulativní chyby před převodem zpět na plovoucí.
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ýstup:
Intermediate Result: 0.2 Final Result: 0.2>
Závěr
Přesto přemýšlíte proč python tento problém neřeší , ve skutečnosti to nemá nic společného s pythonem. Stává se to proto, že je to způsob, jakým základní platforma c zpracovává čísla s plovoucí desetinnou čárkou a nakonec s nepřesností budeme vždy zapisovat čísla jako řetězec pevného počtu číslic. Všimněte si, že je to v samotné povaze binární pohyblivé řádové čárky: ani to není chyba Krajta nebo C a není to chyba ani ve vašem kódu. Uvidíte stejný druh chování ve všech jazycích, které podporují aritmetiku našeho hardwaru s plovoucí desetinnou čárkou, i když některé jazyky nemusí zobrazovat rozdíl ve výchozím nastavení nebo ve všech výstupních režimech). Toto chování musíme vzít v úvahu, když se zajímáme o matematické problémy s potřebami přesné přesnosti nebo je používáme v podmíněných příkazech. Šek plovoucí bod sekce v dokumentaci pythonu pro více takových chování.
Často kladené otázky (FAQ)
1. Co je chyba s plovoucí desetinnou čárkou v Pythonu?
Chyba s plovoucí desetinnou čárkou v Pythonu odkazuje na nesrovnalosti mezi očekávanými a skutečnými výsledky při práci s čísly s plovoucí desetinnou čárkou, které vyplývají z omezení reprezentace reálných čísel v binárním systému.
2. Proč ano? 1.2 - 1.0> ne rovné 0.2> v Pythonu?
Rozpor je způsoben inherentními problémy při reprezentaci desetinných čísel v binárním systému. Během interní binární reprezentace dochází k zaokrouhlovacím chybám, což vede k neočekávaným výsledkům.
3. Je chyba s plovoucí desetinnou čárkou chybou v Pythonu?
Ne, není to chyba v Pythonu. Je to běžný problém ve výpočtech související s tím, jak jsou čísla s plovoucí desetinnou čárkou interně reprezentována. Python dodržuje standard IEEE 754 pro aritmetiku s plovoucí desetinnou čárkou.
4. Jak mohu zaokrouhlit výsledek s plovoucí desetinnou čárkou na konkrétní desetinné místo?
Můžete použít
round()>funkce k zaokrouhlení výsledku s plovoucí desetinnou čárkou na konkrétní desetinné místo. Například,rounded_result = round(result, 2)>.
5. Co je decimal> modul a jak pomáhá zvládnout chyby s plovoucí desetinnou čárkou?
The
decimal>modul poskytujeDecimal>třídy pro vyšší přesnost aritmetiky. Nastavení přesnosti a použitíDecimal>může pomoci zmírnit chyby s plovoucí desetinnou čárkou.