logo

Chyba s plovoucí desetinnou čárkou v Pythonu

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

  1. 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.
  2. 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žítround()>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?

Thedecimal>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.