logo

Python slankiojo kablelio klaida

Python, plačiai naudojama programavimo kalba, puikiai atlieka skaitmeninio skaičiavimo užduotis, tačiau ji nėra apsaugota nuo iššūkių, kuriuos kelia slankiojo kablelio aritmetika. Slankaus kablelio skaičiai Python yra realiųjų skaičių apytiksliai, vedantys į apvalinimo klaidos, tikslumo praradimas ir atšaukimai tai gali sugadinti skaičiavimus. Mes galime pastebėkite šias klaidas ieškodami keistų rezultatų ir naudojant įrankiusnumpy.finfo>į monitoriaus tikslumas . Su tam tikru atsargumu ir sumaniais triukais galime patikrinkite šias klaidas ir užtikrinti, kad mūsų Python skaičiavimai būtų patikimi. Šiame straipsnyje mes išnagrinėsime slankiojo kablelio klaidų sudėtingumą Python .

Kas yra slankiojo kablelio skaičiai?

Slankaus kablelio skaičiai yra efektyvus būdas kompiuteriuose vaizduoti tikrus skaičius. Jie susideda iš trijų dalių:



  • Reikšmingas: Tikrieji skaičiai, nurodantys skaičių (pvz., 3,14159)
  • Rodiklis: Nurodo, kiek vietų reikia perkelti reikšmę į kairę arba į dešinę (pvz., -2 iš 3,14159 x 10^-2)
  • Bazė: Paprastai 2 kompiuteriams, nustatant, kaip skaičiai pateikiami viduje

Kodėl atsiranda slankiojo kablelio klaidos?

Slankiojo kablelio klaidos atsiranda todėl, kad kompiuteriai išsaugo tikrus skaičius, naudodami baigtinį bitų skaičių, todėl susidaro apytiksliai ir galimi netikslumai. Slankaus kablelio skaičiai turi esminių apribojimų:

  • Baigtinis tikslumas: Reikšmėje gali būti išsaugotas tik ribotas skaitmenų skaičius, vedantis į apvalinimo klaidos kai pateikiami tikslūs dešimtainiai.
  • Tikslumo praradimas: Tokios operacijos kaip sudėjimas ar atimtis gali dar labiau sumažinti tikslumą ir sustiprinti apvalinimo poveikį.
  • Perpildymas / perpildymas: Itin maži arba dideli skaičiai gali iškristi už reprezentuojamo diapazono, todėl perteklius (tampa nuliu) arba perpildymas (tampa begalybe).

Slankiojo kablelio klaidų tipai

a) Apvalinimo klaidos: Dažniausiai pasitaikantis, kai turi būti apytikslis tikslus dešimtainis skaičius, kad jis atitiktų ribotą plūdės tikslumą.

b) Tikslumo praradimas: Vėlesnėse operacijose gali palaipsniui kauptis apvalinimo klaidos, todėl galutiniame rezultate gali atsirasti didelių netikslumų.



c) Katastrofiškas atšaukimas: Atimant beveik vienodus skaičius su priešingais ženklais, jų reikšmingieji skaitmenys panaikinami, todėl rezultatas yra mažas ir netikslus.

d) Perpildymas / perpildymas: Taip atsitinka, kai skaičiavimai viršija slankiųjų verčių diapazoną, todėl gaunami netikslūs arba beprasmiai rezultatai.

Slankaus kablelio klaidų aptikimas

  1. Stebėti netikėtus rezultatus: Palyginus apskaičiuotas reikšmes su laukiamais rezultatais arba vizualizuojant duomenis, gali atsirasti neatitikimų, kuriuos dažnai sukelia klaidos.
  2. Naudojant tokias bibliotekas kaip numpy.finfo> : Bibliotekoms patinkanumpy>suteikti tokius įrankiusfinfo>patikrinti skirtingų plaukiojančių duomenų tipų tikslumą ir apribojimus.

Python slankiojo kablelio klaida

Čia aptarsime įvairių tipų pavyzdžius, iliustruojančius Python slankiojo kablelio klaidas:



Tikslumo praradimas konvertuojant dešimtainę į dvejetainę

Šiame pavyzdyje dešimtainis skaičius 0,1 paverčiamas dvejetainiu. Dėl begalinio dvejetainio išplėtimo 0,1 naudojamas tik baigtinis bitų skaičius, todėl prarandamas tikslumas.

Python3




decimal_number>=> 0.1> binary_representation>=> format>(decimal_number,>'.30f'>)># 30 decimal places> print>(f>'Decimal: {decimal_number} Binary: {binary_representation}'>)>

>

>

Išvestis:

Decimal: 0.1 Binary: 0.100000000000000005551115123126>

Apvalinimo klaidos

Čia tikimasi, kad pridėjus 1/3 tris kartus rezultatas bus 1,0. Tačiau dėl apvalinimo klaidų pateikiant 1/3, suma gali būti ne visai lygi 1,0.

Python3




result>=> 1.0> /> 3.0> sum_result>=> result>+> result>+> result> print>(f>'Expected Result: 1.0 Actual Result: {sum_result}'>)>

>

>

Išvestis:

Expected Result: 1.0 Actual Result: 1.0>

Kaupiamosios klaidos kartotiniuose skaičiavimuose

Šis pavyzdys parodo, kaip iteraciniuose skaičiavimuose gali atsirasti kaupiamųjų klaidų. Dešimt kartų pridėjus 0,1 tikslaus rezultato 1,0 gali nepavykti gauti dėl slankiojo kablelio tikslumo apribojimų.

Python3




total>=> 0.0> for> i>in> range>(>10>):> >total>+>=> 0.1> print>(f>'Expected Result: 1.0 Actual Result: {total}'>)>

>

>

Išvestis:

Expected Result: 1.0 Actual Result: 0.9999999999999999>

Palyginimo problemos

Tokiu atveju 0,1 ir 0,2 sumų palyginimas su 0,3 gali neduoti laukiamoTrue>rezultatas dėl būdingo slankiojo kablelio skaičių netikslumo.

Python3




a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a} b: {b} Equal: {a == b}'>)>

>

>

Išvestis:

ex iš vartotojo vardo
a: 0.30000000000000004 b: 0.3 Equal: False>

Netikėti skaičiavimų rezultatai

Čia atimta1e16>nuo sumos(1e16 + 1)>tikimasi gauti 1, bet dėl ​​slankiojo kablelio klaidų rezultatas gali būti ne tiksliai 1.

Python3




a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a} b: {b} Equal: {a == b}'>)>

>

>

Išvestis:

Expected Result: 1 Actual Result: 0.0>

Slankaus kablelio tikslumo supratimas

Čia mes suprasime slankiojo kablelio tikslumą: 1.2–1.0 anomalija Python-

Atstovavimo iššūkiai

Kaip žinia, 1,2 – 1,0 = 0,2. Bet kai bandysite tą patį padaryti Python, jus nustebins rezultatai:

>>> 1,2 - 1,0>

Išvestis:

0.199999999999999996>

Tai gali būti laikoma Python klaida, bet taip nėra. Tai mažai susiję su Python ir daug daugiau su tuo, kaip pagrindinė platforma tvarko slankiojo kablelio skaičius. Tai įprastas atvejis, kai sistemoje tvarkomi slankaus kablelio skaičiai. Tai problema, kurią sukelia vidinis slankaus kablelio skaičių atvaizdavimas, kuris naudoja fiksuotą dvejetainių skaitmenų skaičių dešimtainiam skaičiui pavaizduoti. Sunku pateikti kai kuriuos dešimtainius skaičius dvejetainiu būdu, todėl daugeliu atvejų tai sukelia mažas apvalinimo klaidas. Žinome panašius dešimtainės matematikos atvejus, daugelio rezultatų negalima pateikti fiksuotu dešimtainių skaitmenų skaičiumi, Pavyzdys

10 / 3 = 3.33333333.......>

Šiuo atveju, kaip pavyzdį imant 1,2, 0,2 atvaizdavimas dvejetainiu formatu yra 0,00110011001100110011001100…… ir pan. Sunku išsaugoti šį begalinį dešimtainį skaičių viduje. Paprastai slankiojo objekto vertė yra saugoma dvejetainiame slankiajame kablelyje fiksuotu tikslumu ( paprastai 53 bitai ). Taigi mes atstovaujame 1.2 viduje kaip,

1.0011001100110011001100110011001100110011001100110011>

Kuris yra tiksliai lygus:

1.1999999999999999555910790149937383830547332763671875>

Slankaus kablelio tvarkymo klaida

Čia aptarsime kitą pavyzdį, kaip tvarkyti slankiojo kablelio klaidas Python:

Suapvalinimas iki konkretaus po kablelio

Suapvalindami rezultatą iki konkretaus po kablelio (pvz., 2), galite sušvelninti mažų slankiojo kablelio klaidų poveikį.

Python3




result>=> 1.2> -> 1.0> rounded_result>=> round>(result,>2>)> print>(f>'Original Result: {result} Rounded Result: {rounded_result}'>)>

>

>

Išvestis:

Original Result: 0.19999999999999996 Rounded Result: 0.2>

Dešimtainės klasės naudojimas siekiant didelio tikslumo

Thedecimal>modulis suteikiaDecimal>klasė, leidžianti atlikti didesnį aritmetikos tikslumą. Tikslumo nustatymas sugetcontext().prec>gali padėti valdyti konkrečių skaičiavimų tikslumą

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}'>)>

>

>

Išvestis:

High Precision Result: 0.2>

Trupmenų naudojimas tiksliam vaizdavimui

Thefractions>modulis leidžia dirbti su tiksliomis trupmenomis, išvengiant slankiojo kablelio klaidų.

Python3




from> fractions>import> Fraction> result>=> Fraction(>'1.2'>)>-> Fraction(>'1.0'>)> print>(f>'Exact Fractional Result: {result}'>)>

>

>

Išvestis:

Exact Fractional Result: 1/5>

Tarpinių rezultatų tvarkymas su dešimtainiu

NaudotiDecimal>klasė tarpiniams skaičiavimams, siekiant sumažinti kaupiamąsias klaidas prieš konvertuojant atgal į plūduriuojančią.

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}'>)>

>

>

Išvestis:

Intermediate Result: 0.2 Final Result: 0.2>

Išvada

Vis tiek galvoji kodėl Python šios problemos neišsprendžia , iš tikrųjų tai neturi nieko bendra su python. Taip nutinka todėl, kad pagrindinėje c platformoje taip elgiamasi su slankiojo kablelio skaičiais, ir galiausiai dėl netikslumo skaičius visada užrašydavome kaip fiksuoto skaičiaus skaitmenų eilutę. Atminkite, kad tai yra dvejetainio slankiojo kablelio prigimtis: tai taip pat nėra klaida Python arba C , ir tai nėra jūsų kodo klaida. Matysite vienodą elgseną visomis kalbomis, kurios palaiko mūsų aparatinės įrangos slankiojo kablelio aritmetiką, nors kai kuriose kalbose skirtumas gali būti nerodomas pagal numatytuosius nustatymus arba ne visais išvesties režimais. Turime atsižvelgti į šį elgesį, kai mums rūpi matematikos problemos, reikalaujančios tikslaus tikslumo arba naudojant ją sąlyginiuose teiginiuose. Patikrinti slankusis kablelis python dokumentacijos skyriuje, kur rasite daugiau tokių elgsenų.

Dažnai užduodami klausimai (DUK)

1. Kas yra Python slankiojo kablelio klaida?

Python slankiojo kablelio klaida reiškia neatitikimus tarp laukiamų ir faktinių rezultatų dirbant su slankiojo kablelio skaičiais, atsirandančius dėl realių skaičių vaizdavimo dvejetainėje sistemoje apribojimų.

2. Kodėl taip 1.2 - 1.0> nėra lygus 0.2> Python?

Neatitikimas atsiranda dėl sudėtingų dešimtainių skaičių vaizdavimo dvejetainiu būdu. Apvalinimo klaidos atsiranda atliekant vidinį dvejetainį vaizdavimą, todėl gaunami netikėti rezultatai.

3. Ar slankiojo kablelio klaida yra Python klaida?

Ne, tai nėra Python klaida. Tai dažna skaičiavimo problema, susijusi su tuo, kaip slankiojo kablelio skaičiai pateikiami viduje. Python laikosi IEEE 754 standarto, skirto slankiojo kablelio aritmetikai.

4. Kaip suapvalinti slankiojo kablelio rezultatą iki konkretaus po kablelio?

Galite naudotiround()>funkcija suapvalinti slankiojo kablelio rezultatą iki konkretaus po kablelio. Pavyzdžiui,rounded_result = round(result, 2)>.

5. Kas yra decimal> modulis ir kaip jis padeda tvarkyti slankiojo kablelio klaidas?

Thedecimal>modulis suteikiaDecimal>klasė, skirta didesnio tikslumo aritmetikai. Tikslumo nustatymas ir naudojimasDecimal>gali padėti sumažinti slankiojo kablelio klaidas.