Python, široko uporabljan programski jezik, je odličen pri numeričnih računalniških nalogah, vendar ni imun na izzive, ki jih predstavlja aritmetika s plavajočo vejico. Številke s plavajočo vejico v Pythonu so približki realnih števil, kar vodi do napake pri zaokroževanju, izguba natančnosti in preklice ki lahko zmoti izračune. Mi lahko odkrijte te napake tako, da poiščete čudne rezultate in uporabo orodijnumpy.finfo>do natančnost monitorja . Z nekaj previdnosti in spretnimi triki nam lahko nadzorujte te napake in zagotoviti, da so naši izračuni Python zanesljivi. V tem članku bomo raziskali zapletenost napak v plavajoči vejici Python .
Kaj so števila s plavajočo vejico?
Številke s plavajočo vejico so učinkovit način za predstavitev realnih števil v računalnikih. Sestavljeni so iz treh delov:
- Pomembna: Dejanske števke, ki predstavljajo število (npr. 3,14159)
- Eksponent: Pove, koliko mest je treba premakniti signifikand v levo ali desno (npr. -2 v 3,14159 x 10^-2)
- Osnova: Običajno 2 za računalnike, ki določajo, kako so števila interno predstavljena
Zakaj prihaja do napak v plavajoči vejici?
Napake s plavajočo vejico se pojavijo, ker računalniki shranjujejo realna števila z uporabo končnega števila bitov, kar vodi do približkov in morebitnih netočnosti. Številke s plavajočo vejico imajo notranje omejitve:
- Končna natančnost: V signifikandu je mogoče shraniti le omejeno število števk, kar vodi do napake pri zaokroževanju pri predstavljanju natančnih decimalk.
- Izguba natančnosti: Operacije, kot sta seštevanje ali odštevanje, lahko dodatno zmanjšajo natančnost in povečajo učinke zaokroževanja.
- Spodnji/prelivni: Izjemno majhne ali velike številke lahko padejo izven reprezentativnega obsega, kar vodi do podtok (postane nič) oz preliv (postane neskončnost).
Vrste napak s plavajočo vejico
a) Napake pri zaokroževanju: Najpogostejši, ki se pojavi, ko je treba točno decimalko približati, da ustreza omejeni natančnosti lebdečega.
b) Izguba natančnosti: Naslednje operacije lahko postopoma kopičijo napake pri zaokroževanju, kar vodi do znatnih netočnosti končnega rezultata.
c) Katastrofalna odpoved: Pri odštevanju skoraj enakih števil z nasprotnimi predznaki se njihove pomembne števke izničijo, tako da ostane majhen in netočen rezultat.
d) Prelivanje/Prelivanje: Do teh pride, ko izračuni presežejo reprezentativni obseg plavajočih vrednosti, kar vodi do netočnih ali nesmiselnih rezultatov.
Odkrivanje napak s plavajočo vejico
- Opazovanje nepričakovanih rezultatov: Primerjava izračunanih vrednosti s pričakovanimi rezultati ali vizualizacija podatkov lahko razkrije nedoslednosti, ki jih pogosto povzročijo napake.
- Uporaba knjižnic, kot je
numpy.finfo>: Knjižnice kotnumpy>zagotoviti orodja, kot jefinfo>za preverjanje natančnosti in omejitev različnih podatkovnih tipov float.
Napaka Python s plavajočo vejico
Tukaj bomo razpravljali o različnih vrstah primerov, ki ponazarjajo napake s plavajočo vejico v Pythonu:
Izguba natančnosti pri pretvorbi decimalne v dvojiško
V tem primeru je decimalno število 0,1 pretvorjeno v dvojiško. Zaradi neskončne binarne razširitve 0,1 se uporablja samo končno število bitov, kar vodi do izgube natančnosti.
Python3
decimal_number>=> 0.1> binary_representation>=> format>(decimal_number,>'.30f'>)># 30 decimal places> print>(f>'Decimal: {decimal_number}
Binary: {binary_representation}'>)> |
>
>
Izhod:
Decimal: 0.1 Binary: 0.100000000000000005551115123126>
Napake pri zaokroževanju
Tukaj se pričakuje, da bo rezultat trikratnega seštevanja 1/3 1,0. Vendar pa zaradi napak pri zaokroževanju pri predstavljanju 1/3 vsota morda ne bo točno 1,0.
Python3
linux ukazi
result>=> 1.0> /> 3.0> sum_result>=> result>+> result>+> result> print>(f>'Expected Result: 1.0
Actual Result: {sum_result}'>)> |
>
>
Izhod:
Expected Result: 1.0 Actual Result: 1.0>
Kumulativne napake v iterativnih izračunih
Ta primer prikazuje, kako lahko pride do kopičnih napak pri ponavljajočih se izračunih. Desetkratno dodajanje 0,1 morda ne bo dalo natančnega rezultata 1,0 zaradi omejitev natančnosti plavajoče vejice.
Python3
total>=> 0.0> for> i>in> range>(>10>):> >total>+>=> 0.1> print>(f>'Expected Result: 1.0
Actual Result: {total}'>)> |
>
>
Izhod:
Expected Result: 1.0 Actual Result: 0.9999999999999999>
Težave s primerjavo
V tem primeru primerjava vsote 0,1 in 0,2 do 0,3 morda ne bo prinesla pričakovanegaTrue>rezultat zaradi inherentne nenatančnosti števil s plavajočo vejico.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Izhod:
a: 0.30000000000000004 b: 0.3 Equal: False>
Nepričakovani rezultati v izračunih
Tukaj je odštevanje1e16>od vsote(1e16 + 1)>naj bi dal 1, vendar zaradi napak v plavajoči vejici rezultat morda ne bo točno 1.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Izhod:
Expected Result: 1 Actual Result: 0.0>
Razumevanje natančnosti s plavajočo vejico
Tukaj bomo razumeli natančnost plavajoče vejice: Anomalija 1.2 – 1.0 v Python-u
Reprezentančni izzivi
Kot je znano, je 1,2 – 1,0 = 0,2. Toda ko poskusite narediti isto v Pythonu, boste presenečeni nad rezultati:
>>> 1,2 - 1,0>>
Izhod:
0.199999999999999996>
To se lahko šteje za napako v Pythonu, vendar ni. To nima veliko opraviti s Pythonom in veliko bolj s tem, kako osnovna platforma obravnava števila s plavajočo vejico. To je običajen primer, ko interno obravnavamo števila s plavajočo vejico v sistemu. To je težava, ki jo povzroča notranja predstavitev števil s plavajočo vejico, ki za predstavitev decimalnega števila uporablja fiksno število binarnih števk. Nekatera decimalna števila je težko predstaviti v dvojiški obliki, zato v mnogih primerih povzroči majhne napake pri zaokroževanju. Poznamo podobne primere v decimalni matematiki, veliko rezultatov ni mogoče predstaviti s fiksnim številom decimalnih mest, ker Primer
10 / 3 = 3.33333333.......>
V tem primeru, če za primer vzamemo 1,2, je predstavitev 0,2 v binarni obliki 0,00110011001100110011001100…… in tako naprej. To neskončno decimalno število je težko interno shraniti. Običajno je vrednost plavajočega predmeta shranjena v binarni plavajoči vejici s fiksno natančnostjo ( običajno 53 bitov ). Torej predstavljamo 1.2 notranje kot,
1.0011001100110011001100110011001100110011001100110011>
Kar je natančno enako:
1.1999999999999999555910790149937383830547332763671875>
Obravnava napake s plavajočo vejico
Tukaj bomo razpravljali o različnih primerih, kako obravnavati napake s plavajočo vejico v Pythonu:
Zaokroževanje na določeno decimalno mesto
Z zaokroževanjem rezultata na določeno decimalno mesto (npr. 2) lahko ublažite vpliv majhnih napak v plavajoči vejici.
Python3
result>=> 1.2> -> 1.0> rounded_result>=> round>(result,>2>)> print>(f>'Original Result: {result}
Rounded Result: {rounded_result}'>)> |
>
>
Izhod:
Original Result: 0.19999999999999996 Rounded Result: 0.2>
Uporaba decimalnega razreda za visoko natančnost
Thedecimal>modul zagotavljaDecimal>razreda, kar omogoča večjo natančnost aritmetike. Nastavitev natančnosti zgetcontext().prec>lahko pomaga pri upravljanju natančnosti za specifične izračune
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}'>)> |
delni derivat v lateksu
>
>
Izhod:
High Precision Result: 0.2>
Uporaba ulomkov za natančne predstavitve
Thefractions>modul omogoča delo z natančnimi frakcijskimi predstavitvami, pri čemer se izogiba napakam v plavajoči vejici.
Python3
from> fractions>import> Fraction> result>=> Fraction(>'1.2'>)>-> Fraction(>'1.0'>)> print>(f>'Exact Fractional Result: {result}'>)> |
>
>
Izhod:
Exact Fractional Result: 1/5>
Obdelava vmesnih rezultatov z decimalko
UporabiDecimal>razred za vmesne izračune za zmanjšanje kumulativnih napak pred pretvorbo nazaj v 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}'>)> |
>
>
Izhod:
Intermediate Result: 0.2 Final Result: 0.2>
Zaključek
Še vedno razmišljate, zakaj python ne reši te težave , pravzaprav nima nobene zveze s pythonom. To se zgodi, ker je to način, na katerega osnovna platforma c obravnava števila s plavajočo vejico in na koncu zaradi netočnosti bomo vedno zapisovali števila kot niz s fiksnim številom števk. Upoštevajte, da je to v sami naravi binarne plavajoče vejice: tudi to ni napaka v Python oz C , in to tudi ni napaka v vaši kodi. Enako vedenje boste videli v vseh jezikih, ki podpirajo aritmetiko s plavajočo vejico naše strojne opreme, čeprav nekateri jeziki morda ne bodo prikazali razlike privzeto ali v vseh izhodnih načinih). To vedenje moramo upoštevati, ko nas zanimajo matematične težave, ki potrebujejo natančno natančnost ali jih uporabljamo znotraj pogojnih stavkov. Preverite plavajočo vejico razdelek v dokumentaciji python za več takih vedenj.
Pogosto zastavljena vprašanja (FAQ)
1. Kaj je napaka s plavajočo vejico v Pythonu?
Napaka s plavajočo vejico v Pythonu se nanaša na neskladja med pričakovanimi in dejanskimi rezultati pri delu s števili s plavajočo vejico, ki izhajajo iz omejitev predstavljanja realnih števil v binarnem sistemu.
2. Zakaj 1.2 - 1.0> ni enako 0.2> v Pythonu?
Neskladje je posledica inherentnih izzivov pri predstavitvi decimalnih števil v dvojiški obliki. Med notranjo binarno predstavitvijo se pojavijo napake pri zaokroževanju, kar vodi do nepričakovanih rezultatov.
3. Ali je napaka s plavajočo vejico napaka v Pythonu?
Ne, to ni napaka v Pythonu. To je pogosta težava v računalništvu, povezana s tem, kako so števila s plavajočo vejico interno predstavljena. Python se drži standarda IEEE 754 za aritmetiko s plavajočo vejico.
4. Kako lahko zaokrožim rezultat s plavajočo vejico na določeno decimalno mesto?
Lahko uporabite
round()>funkcija za zaokroževanje rezultata s plavajočo vejico na določeno decimalno mesto. na primerrounded_result = round(result, 2)>.
5. Kaj je decimal> modul in kako pomaga pri obravnavi napak s plavajočo vejico?
The
decimal>modul zagotavljaDecimal>razred za večjo natančnost aritmetike. Nastavitev natančnosti in uporabaDecimal>lahko pomaga ublažiti napake s plavajočo vejico.